From a1f0f73a4090d63120b59ef9a87be6fe8f22bd5c Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Wed, 8 Jan 2025 17:33:12 -0500 Subject: [PATCH 1/8] xdrill for ledgerCloseMeta --- exp/xdrill/ledger.go | 248 ++++++++++++++++++++++++++++++++++++++ exp/xdrill/ledger_test.go | 168 ++++++++++++++++++++++++++ exp/xdrill/utils/utils.go | 92 ++++++++++++++ go.mod | 1 + go.sum | 2 + 5 files changed, 511 insertions(+) create mode 100644 exp/xdrill/ledger.go create mode 100644 exp/xdrill/ledger_test.go create mode 100644 exp/xdrill/utils/utils.go diff --git a/exp/xdrill/ledger.go b/exp/xdrill/ledger.go new file mode 100644 index 0000000000..3095094d85 --- /dev/null +++ b/exp/xdrill/ledger.go @@ -0,0 +1,248 @@ +package xdrill + +import ( + "encoding/base64" + "fmt" + "time" + + "github.com/stellar/go/exp/xdrill/utils" + "github.com/stellar/go/keypair" + "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" +) + +type Ledger struct { + ledger *xdr.LedgerCloseMeta +} + +func (l Ledger) Sequence() uint32 { + return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) +} + +func (l Ledger) ID() int64 { + return utils.NewID(int32(l.Sequence()), 0, 0).ToInt64() +} + +func (l Ledger) Hash() string { + return utils.HashToHexString(l.ledger.LedgerHeaderHistoryEntry().Hash) +} + +func (l Ledger) PreviousHash() string { + return utils.HashToHexString(l.ledger.PreviousLedgerHash()) +} + +func (l Ledger) CloseTime() int64 { + return l.ledger.LedgerCloseTime() +} + +func (l Ledger) ClosedAt() time.Time { + return time.Unix(l.CloseTime(), 0).UTC() +} + +func (l Ledger) TotalCoins() int64 { + return int64(l.ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) +} + +func (l Ledger) FeePool() int64 { + return int64(l.ledger.LedgerHeaderHistoryEntry().Header.FeePool) +} + +func (l Ledger) BaseFee() uint32 { + return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.BaseFee) +} + +func (l Ledger) BaseReserve() uint32 { + return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) +} + +func (l Ledger) MaxTxSetSize() uint32 { + return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) +} + +func (l Ledger) LedgerVersion() uint32 { + return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) +} + +func (l Ledger) SorobanFeeWrite1Kb() (int64, bool) { + lcmV1, ok := l.ledger.GetV1() + if !ok { + return 0, false + } + + extV1, ok := lcmV1.Ext.GetV1() + if !ok { + return 0, false + } + + return int64(extV1.SorobanFeeWrite1Kb), true +} + +func (l Ledger) TotalByteSizeOfBucketList() (uint64, bool) { + lcmV1, ok := l.ledger.GetV1() + if !ok { + return 0, false + } + + return uint64(lcmV1.TotalByteSizeOfBucketList), true +} + +func (l Ledger) NodeID() (string, bool) { + LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + if !ok { + return "", false + + } + nodeID, ok := utils.GetAddress(LedgerCloseValueSignature.NodeId) + if !ok { + return "", false + } + + return nodeID, true +} + +func (l Ledger) Signature() (string, bool) { + LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + if !ok { + return "", false + } + + return base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature), true +} + +// Add docstring to larger, more complicated functions +func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok bool) { + var results []xdr.TransactionResultMeta + + transactions := getTransactionSet(l) + switch l.ledger.V { + case 0: + results = l.ledger.V0.TxProcessing + case 1: + results = l.ledger.V1.TxProcessing + } + 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 +} + +// Add docstring to larger, more complicated functions +func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok bool) { + var results []xdr.TransactionResultMeta + + transactions := getTransactionSet(l) + switch l.ledger.V { + case 0: + results = l.ledger.V0.TxProcessing + case 1: + results = l.ledger.V1.TxProcessing + } + + 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 Ledger) (transactionProcessing []xdr.TransactionEnvelope) { + switch l.ledger.V { + case 0: + return l.ledger.V0.TxSet.Txs + case 1: + switch l.ledger.V1.TxSet.V { + case 0: + return getTransactionPhase(l.ledger.V1.TxSet.V1TxSet.Phases) + default: + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.ledger.V1.TxSet.V)) + } + default: + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.ledger.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 +} + +func CreateSampleTx(sequence int64, operationCount int) xdr.TransactionEnvelope { + kp, err := keypair.Random() + PanicOnError(err) + + operations := []txnbuild.Operation{} + operationType := &txnbuild.BumpSequence{ + BumpTo: 0, + } + for i := 0; i < operationCount; i++ { + operations = append(operations, operationType) + } + + sourceAccount := txnbuild.NewSimpleAccount(kp.Address(), int64(0)) + tx, err := txnbuild.NewTransaction( + txnbuild.TransactionParams{ + SourceAccount: &sourceAccount, + Operations: operations, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, + }, + ) + PanicOnError(err) + + env := tx.ToXDR() + return env +} + +// PanicOnError is a function that panics if the provided error is not nil +func PanicOnError(err error) { + if err != nil { + panic(err) + } +} diff --git a/exp/xdrill/ledger_test.go b/exp/xdrill/ledger_test.go new file mode 100644 index 0000000000..febdf65d45 --- /dev/null +++ b/exp/xdrill/ledger_test.go @@ -0,0 +1,168 @@ +package xdrill + +import ( + "testing" + "time" + + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" +) + +func TestLedger(t *testing.T) { + ledger := Ledger{ + ledger: ledgerTestInput(), + } + + assert.Equal(t, uint32(30578981), ledger.Sequence()) + assert.Equal(t, int64(131335723340005376), ledger.ID()) + assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", ledger.Hash()) + assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", ledger.PreviousHash()) + assert.Equal(t, int64(1594584547), ledger.CloseTime()) + assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ledger.ClosedAt()) + assert.Equal(t, int64(1054439020873472865), ledger.TotalCoins()) + assert.Equal(t, int64(18153766209161), ledger.FeePool()) + assert.Equal(t, uint32(100), ledger.BaseFee()) + assert.Equal(t, uint32(5000000), ledger.BaseReserve()) + assert.Equal(t, uint32(1000), ledger.MaxTxSetSize()) + assert.Equal(t, uint32(13), ledger.LedgerVersion()) + + var ok bool + + var freeWrite int64 + freeWrite, ok = ledger.SorobanFeeWrite1Kb() + assert.Equal(t, true, ok) + assert.Equal(t, int64(12), freeWrite) + + var bucketSize uint64 + bucketSize, ok = ledger.TotalByteSizeOfBucketList() + assert.Equal(t, true, ok) + assert.Equal(t, uint64(56), bucketSize) + + var nodeID string + nodeID, ok = ledger.NodeID() + assert.Equal(t, true, ok) + assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", nodeID) + + var signature string + signature, ok = ledger.Signature() + assert.Equal(t, true, ok) + assert.Equal(t, "", signature) + + var success int32 + var failed int32 + success, failed, ok = ledger.TransactionCounts() + assert.Equal(t, true, ok) + assert.Equal(t, int32(1), success) + assert.Equal(t, int32(1), failed) + + success, failed, ok = ledger.OperationCounts() + assert.Equal(t, true, ok) + assert.Equal(t, int32(1), success) + assert.Equal(t, int32(13), failed) + +} + +func ledgerTestInput() (lcm *xdr.LedgerCloseMeta) { + lcm = &xdr.LedgerCloseMeta{ + V: 1, + V1: &xdr.LedgerCloseMetaV1{ + Ext: xdr.LedgerCloseMetaExt{ + V: 1, + V1: &xdr.LedgerCloseMetaExtV1{ + SorobanFeeWrite1Kb: xdr.Int64(12), + }, + }, + LedgerHeader: xdr.LedgerHeaderHistoryEntry{ + Hash: xdr.Hash{0x26, 0x93, 0x2d, 0xc4, 0xd8, 0x4b, 0x5f, 0xab, 0xe9, 0xae, 0x74, 0x4c, 0xb4, 0x3c, 0xe4, 0xc6, 0xda, 0xcc, 0xf9, 0x8c, 0x86, 0xa9, 0x91, 0xb2, 0xa1, 0x49, 0x45, 0xb1, 0xad, 0xac, 0x4d, 0x59}, + Header: xdr.LedgerHeader{ + LedgerSeq: 30578981, + TotalCoins: 1054439020873472865, + FeePool: 18153766209161, + BaseFee: 100, + BaseReserve: 5000000, + MaxTxSetSize: 1000, + LedgerVersion: 13, + PreviousLedgerHash: xdr.Hash{0xf6, 0x3c, 0x15, 0xd0, 0xea, 0xf4, 0x8a, 0xfb, 0xd7, 0x51, 0xa4, 0xc4, 0xdf, 0xad, 0xe5, 0x4a, 0x34, 0x48, 0x5, 0x3c, 0x47, 0xc5, 0xa7, 0x1d, 0x62, 0x26, 0x68, 0xae, 0xc, 0xc2, 0xa2, 0x8}, + ScpValue: xdr.StellarValue{ + Ext: xdr.StellarValueExt{ + V: 1, + LcValueSignature: &xdr.LedgerCloseValueSignature{ + NodeId: xdr.NodeId{ + Type: 0, + Ed25519: &xdr.Uint256{34}, + }, + }, + }, + CloseTime: 1594584547, + }, + }, + }, + TotalByteSizeOfBucketList: xdr.Uint64(56), + TxSet: xdr.GeneralizedTransactionSet{ + V: 0, + V1TxSet: &xdr.TransactionSetV1{ + Phases: []xdr.TransactionPhase{ + { + V: 0, + V0Components: &[]xdr.TxSetComponent{ + { + Type: 0, + TxsMaybeDiscountedFee: &xdr.TxSetComponentTxsMaybeDiscountedFee{ + Txs: []xdr.TransactionEnvelope{ + CreateSampleTx(0, 3), + CreateSampleTx(1, 10), + }, + }, + }, + }, + }, + }, + }, + }, + TxProcessing: []xdr.TransactionResultMeta{ + { + Result: xdr.TransactionResultPair{ + Result: xdr.TransactionResult{ + Result: xdr.TransactionResultResult{ + Code: xdr.TransactionResultCodeTxSuccess, + Results: &[]xdr.OperationResult{ + { + Code: xdr.OperationResultCodeOpInner, + Tr: &xdr.OperationResultTr{ + Type: xdr.OperationTypeCreateAccount, + CreateAccountResult: &xdr.CreateAccountResult{ + Code: 0, + }, + }, + }, + }, + }, + }, + }, + }, + { + Result: xdr.TransactionResultPair{ + Result: xdr.TransactionResult{ + Result: xdr.TransactionResultResult{ + Code: xdr.TransactionResultCodeTxFailed, + Results: &[]xdr.OperationResult{ + { + Code: xdr.OperationResultCodeOpInner, + Tr: &xdr.OperationResultTr{ + Type: xdr.OperationTypeCreateAccount, + CreateAccountResult: &xdr.CreateAccountResult{ + Code: 0, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + return lcm +} diff --git a/exp/xdrill/utils/utils.go b/exp/xdrill/utils/utils.go new file mode 100644 index 0000000000..0bc8d30c3e --- /dev/null +++ b/exp/xdrill/utils/utils.go @@ -0,0 +1,92 @@ +package utils + +import ( + "encoding/hex" + + "github.com/stellar/go/strkey" + "github.com/stellar/go/xdr" +) + +// HashToHexString is utility function that converts and xdr.Hash type to a hex string +func HashToHexString(inputHash xdr.Hash) string { + sliceHash := inputHash[:] + hexString := hex.EncodeToString(sliceHash) + return hexString +} + +type ID struct { + LedgerSequence int32 + TransactionOrder int32 + OperationOrder int32 +} + +const ( + // LedgerMask is the bitmask to mask out ledger sequences in a + // TotalOrderID + LedgerMask = (1 << 32) - 1 + // TransactionMask is the bitmask to mask out transaction indexes + TransactionMask = (1 << 20) - 1 + // OperationMask is the bitmask to mask out operation indexes + OperationMask = (1 << 12) - 1 + + // LedgerShift is the number of bits to shift an int64 to target the + // ledger component + LedgerShift = 32 + // TransactionShift is the number of bits to shift an int64 to + // target the transaction component + TransactionShift = 12 + // OperationShift is the number of bits to shift an int64 to target + // the operation component + OperationShift = 0 +) + +// New creates a new total order ID +func NewID(ledger int32, tx int32, op int32) *ID { + return &ID{ + LedgerSequence: ledger, + TransactionOrder: tx, + OperationOrder: op, + } +} + +// ToInt64 converts this struct back into an int64 +func (id ID) ToInt64() (result int64) { + + if id.LedgerSequence < 0 { + panic("invalid ledger sequence") + } + + if id.TransactionOrder > TransactionMask { + panic("transaction order overflow") + } + + if id.OperationOrder > OperationMask { + panic("operation order overflow") + } + + result = result | ((int64(id.LedgerSequence) & LedgerMask) << LedgerShift) + result = result | ((int64(id.TransactionOrder) & TransactionMask) << TransactionShift) + result = result | ((int64(id.OperationOrder) & OperationMask) << OperationShift) + return +} + +// TODO: This should be moved into the go monorepo xdr functions +// Or nodeID should just be an xdr.AccountId but the error message would be incorrect +func GetAddress(nodeID xdr.NodeId) (string, bool) { + switch nodeID.Type { + case xdr.PublicKeyTypePublicKeyTypeEd25519: + ed, ok := nodeID.GetEd25519() + if !ok { + return "", false + } + raw := make([]byte, 32) + copy(raw, ed[:]) + encodedAddress, err := strkey.Encode(strkey.VersionByteAccountID, raw) + if err != nil { + return "", false + } + return encodedAddress, true + default: + return "", false + } +} diff --git a/go.mod b/go.mod index 341c85543e..6d7e5fab5d 100644 --- a/go.mod +++ b/go.mod @@ -58,6 +58,7 @@ require ( require ( github.com/cenkalti/backoff/v4 v4.3.0 + github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/fsouza/fake-gcs-server v1.49.2 diff --git a/go.sum b/go.sum index a3c8ce08fa..b071601459 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/fscache v0.10.1 h1:hDv+RGyvD+UDKyRYuLoVNbuRTnf2SrA2K3VyR1br9lk= From f1f97a9ec38c132461a187763c03f24d8f30e0a8 Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Wed, 8 Jan 2025 17:41:04 -0500 Subject: [PATCH 2/8] go mod tidy --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index 6d7e5fab5d..341c85543e 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,6 @@ require ( require ( github.com/cenkalti/backoff/v4 v4.3.0 - github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/fsouza/fake-gcs-server v1.49.2 diff --git a/go.sum b/go.sum index b071601459..a3c8ce08fa 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= -github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/fscache v0.10.1 h1:hDv+RGyvD+UDKyRYuLoVNbuRTnf2SrA2K3VyR1br9lk= From 36cfcbc9afa0590c7d1a067c5214dfe70496d61c Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Thu, 9 Jan 2025 00:55:01 -0500 Subject: [PATCH 3/8] Move util functions from ledger.go to utils.go --- exp/xdrill/ledger.go | 36 ------------------------------------ exp/xdrill/ledger_test.go | 5 +++-- exp/xdrill/utils/utils.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/exp/xdrill/ledger.go b/exp/xdrill/ledger.go index 3095094d85..e904009d52 100644 --- a/exp/xdrill/ledger.go +++ b/exp/xdrill/ledger.go @@ -6,8 +6,6 @@ import ( "time" "github.com/stellar/go/exp/xdrill/utils" - "github.com/stellar/go/keypair" - "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" ) @@ -212,37 +210,3 @@ func getTransactionPhase(transactionPhase []xdr.TransactionPhase) (transactionEn return transactionSlice } - -func CreateSampleTx(sequence int64, operationCount int) xdr.TransactionEnvelope { - kp, err := keypair.Random() - PanicOnError(err) - - operations := []txnbuild.Operation{} - operationType := &txnbuild.BumpSequence{ - BumpTo: 0, - } - for i := 0; i < operationCount; i++ { - operations = append(operations, operationType) - } - - sourceAccount := txnbuild.NewSimpleAccount(kp.Address(), int64(0)) - tx, err := txnbuild.NewTransaction( - txnbuild.TransactionParams{ - SourceAccount: &sourceAccount, - Operations: operations, - BaseFee: txnbuild.MinBaseFee, - Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, - }, - ) - PanicOnError(err) - - env := tx.ToXDR() - return env -} - -// PanicOnError is a function that panics if the provided error is not nil -func PanicOnError(err error) { - if err != nil { - panic(err) - } -} diff --git a/exp/xdrill/ledger_test.go b/exp/xdrill/ledger_test.go index febdf65d45..7626895abe 100644 --- a/exp/xdrill/ledger_test.go +++ b/exp/xdrill/ledger_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/stellar/go/exp/xdrill/utils" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" ) @@ -109,8 +110,8 @@ func ledgerTestInput() (lcm *xdr.LedgerCloseMeta) { Type: 0, TxsMaybeDiscountedFee: &xdr.TxSetComponentTxsMaybeDiscountedFee{ Txs: []xdr.TransactionEnvelope{ - CreateSampleTx(0, 3), - CreateSampleTx(1, 10), + utils.CreateSampleTx(0, 3), + utils.CreateSampleTx(1, 10), }, }, }, diff --git a/exp/xdrill/utils/utils.go b/exp/xdrill/utils/utils.go index 0bc8d30c3e..645967679e 100644 --- a/exp/xdrill/utils/utils.go +++ b/exp/xdrill/utils/utils.go @@ -3,7 +3,9 @@ package utils import ( "encoding/hex" + "github.com/stellar/go/keypair" "github.com/stellar/go/strkey" + "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" ) @@ -90,3 +92,37 @@ func GetAddress(nodeID xdr.NodeId) (string, bool) { return "", false } } + +func CreateSampleTx(sequence int64, operationCount int) xdr.TransactionEnvelope { + kp, err := keypair.Random() + PanicOnError(err) + + operations := []txnbuild.Operation{} + operationType := &txnbuild.BumpSequence{ + BumpTo: 0, + } + for i := 0; i < operationCount; i++ { + operations = append(operations, operationType) + } + + sourceAccount := txnbuild.NewSimpleAccount(kp.Address(), int64(0)) + tx, err := txnbuild.NewTransaction( + txnbuild.TransactionParams{ + SourceAccount: &sourceAccount, + Operations: operations, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, + }, + ) + PanicOnError(err) + + env := tx.ToXDR() + return env +} + +// PanicOnError is a function that panics if the provided error is not nil +func PanicOnError(err error) { + if err != nil { + panic(err) + } +} From d064296aa0ece071cd1b873d55e346fe97713f4e Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Thu, 9 Jan 2025 01:10:10 -0500 Subject: [PATCH 4/8] change some return values to pointers --- exp/xdrill/ledger.go | 48 ++++++++++++++++++--------------------- exp/xdrill/ledger_test.go | 25 ++++++++------------ xdr/ledger_close_meta.go | 12 ++++++++++ 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/exp/xdrill/ledger.go b/exp/xdrill/ledger.go index e904009d52..88eebde1c6 100644 --- a/exp/xdrill/ledger.go +++ b/exp/xdrill/ledger.go @@ -61,50 +61,56 @@ func (l Ledger) LedgerVersion() uint32 { return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) } -func (l Ledger) SorobanFeeWrite1Kb() (int64, bool) { +func (l Ledger) SorobanFeeWrite1Kb() *int64 { lcmV1, ok := l.ledger.GetV1() if !ok { - return 0, false + return nil } extV1, ok := lcmV1.Ext.GetV1() if !ok { - return 0, false + return nil } - return int64(extV1.SorobanFeeWrite1Kb), true + result := int64(extV1.SorobanFeeWrite1Kb) + + return &result } -func (l Ledger) TotalByteSizeOfBucketList() (uint64, bool) { +func (l Ledger) TotalByteSizeOfBucketList() *uint64 { lcmV1, ok := l.ledger.GetV1() if !ok { - return 0, false + return nil } - return uint64(lcmV1.TotalByteSizeOfBucketList), true + result := uint64(lcmV1.TotalByteSizeOfBucketList) + + return &result } -func (l Ledger) NodeID() (string, bool) { +func (l Ledger) NodeID() *string { LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { - return "", false + return nil } nodeID, ok := utils.GetAddress(LedgerCloseValueSignature.NodeId) if !ok { - return "", false + return nil } - return nodeID, true + return &nodeID } -func (l Ledger) Signature() (string, bool) { +func (l Ledger) Signature() *string { LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { - return "", false + return nil } - return base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature), true + result := base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature) + + return &result } // Add docstring to larger, more complicated functions @@ -112,12 +118,7 @@ func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok boo var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - switch l.ledger.V { - case 0: - results = l.ledger.V0.TxProcessing - case 1: - results = l.ledger.V1.TxProcessing - } + results = l.ledger.TxProcessing() txCount := len(transactions) if txCount != len(results) { return 0, 0, false @@ -139,12 +140,7 @@ func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - switch l.ledger.V { - case 0: - results = l.ledger.V0.TxProcessing - case 1: - results = l.ledger.V1.TxProcessing - } + results = l.ledger.TxProcessing() txCount := len(transactions) if txCount != len(results) { diff --git a/exp/xdrill/ledger_test.go b/exp/xdrill/ledger_test.go index 7626895abe..b5ca0377a1 100644 --- a/exp/xdrill/ledger_test.go +++ b/exp/xdrill/ledger_test.go @@ -29,25 +29,17 @@ func TestLedger(t *testing.T) { var ok bool - var freeWrite int64 - freeWrite, ok = ledger.SorobanFeeWrite1Kb() - assert.Equal(t, true, ok) - assert.Equal(t, int64(12), freeWrite) + freeWrite := ledger.SorobanFeeWrite1Kb() + assert.Equal(t, int64(12), *freeWrite) - var bucketSize uint64 - bucketSize, ok = ledger.TotalByteSizeOfBucketList() - assert.Equal(t, true, ok) - assert.Equal(t, uint64(56), bucketSize) + bucketSize := ledger.TotalByteSizeOfBucketList() + assert.Equal(t, uint64(56), *bucketSize) - var nodeID string - nodeID, ok = ledger.NodeID() - assert.Equal(t, true, ok) - assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", nodeID) + nodeID := ledger.NodeID() + assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", *nodeID) - var signature string - signature, ok = ledger.Signature() - assert.Equal(t, true, ok) - assert.Equal(t, "", signature) + signature := ledger.Signature() + assert.Equal(t, "9g==", *signature) var success int32 var failed int32 @@ -92,6 +84,7 @@ func ledgerTestInput() (lcm *xdr.LedgerCloseMeta) { Type: 0, Ed25519: &xdr.Uint256{34}, }, + Signature: []byte{0xf6}, }, }, CloseTime: 1594584547, diff --git a/xdr/ledger_close_meta.go b/xdr/ledger_close_meta.go index 30e80b2e38..bcb4fd9645 100644 --- a/xdr/ledger_close_meta.go +++ b/xdr/ledger_close_meta.go @@ -156,3 +156,15 @@ func (l LedgerCloseMeta) EvictedPersistentLedgerEntries() ([]LedgerEntry, error) panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) } } + +// TxProcessing returns the TransactionResultMeta in this ledger +func (l LedgerCloseMeta) TxProcessing() []TransactionResultMeta { + switch l.V { + case 0: + return l.MustV0().TxProcessing + case 1: + return l.MustV1().TxProcessing + default: + panic(fmt.Sprintf("Unsupported LedgerCloseMeta.V: %d", l.V)) + } +} From 15fe1e574f47cd9a0d42dc7b86094200db12e9ca Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Thu, 9 Jan 2025 17:01:08 -0500 Subject: [PATCH 5/8] Change ledger to Ledger --- exp/xdrill/ledger.go | 46 +++++++++++++++++++-------------------- exp/xdrill/ledger_test.go | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/exp/xdrill/ledger.go b/exp/xdrill/ledger.go index 88eebde1c6..d794fce04a 100644 --- a/exp/xdrill/ledger.go +++ b/exp/xdrill/ledger.go @@ -10,11 +10,11 @@ import ( ) type Ledger struct { - ledger *xdr.LedgerCloseMeta + Ledger *xdr.LedgerCloseMeta } func (l Ledger) Sequence() uint32 { - return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) } func (l Ledger) ID() int64 { @@ -22,15 +22,15 @@ func (l Ledger) ID() int64 { } func (l Ledger) Hash() string { - return utils.HashToHexString(l.ledger.LedgerHeaderHistoryEntry().Hash) + return utils.HashToHexString(l.Ledger.LedgerHeaderHistoryEntry().Hash) } func (l Ledger) PreviousHash() string { - return utils.HashToHexString(l.ledger.PreviousLedgerHash()) + return utils.HashToHexString(l.Ledger.PreviousLedgerHash()) } func (l Ledger) CloseTime() int64 { - return l.ledger.LedgerCloseTime() + return l.Ledger.LedgerCloseTime() } func (l Ledger) ClosedAt() time.Time { @@ -38,31 +38,31 @@ func (l Ledger) ClosedAt() time.Time { } func (l Ledger) TotalCoins() int64 { - return int64(l.ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) + return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) } func (l Ledger) FeePool() int64 { - return int64(l.ledger.LedgerHeaderHistoryEntry().Header.FeePool) + return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.FeePool) } func (l Ledger) BaseFee() uint32 { - return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.BaseFee) + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseFee) } func (l Ledger) BaseReserve() uint32 { - return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) } func (l Ledger) MaxTxSetSize() uint32 { - return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) } func (l Ledger) LedgerVersion() uint32 { - return uint32(l.ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) } func (l Ledger) SorobanFeeWrite1Kb() *int64 { - lcmV1, ok := l.ledger.GetV1() + lcmV1, ok := l.Ledger.GetV1() if !ok { return nil } @@ -78,7 +78,7 @@ func (l Ledger) SorobanFeeWrite1Kb() *int64 { } func (l Ledger) TotalByteSizeOfBucketList() *uint64 { - lcmV1, ok := l.ledger.GetV1() + lcmV1, ok := l.Ledger.GetV1() if !ok { return nil } @@ -89,7 +89,7 @@ func (l Ledger) TotalByteSizeOfBucketList() *uint64 { } func (l Ledger) NodeID() *string { - LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return nil @@ -103,7 +103,7 @@ func (l Ledger) NodeID() *string { } func (l Ledger) Signature() *string { - LedgerCloseValueSignature, ok := l.ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return nil } @@ -118,7 +118,7 @@ func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok boo var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - results = l.ledger.TxProcessing() + results = l.Ledger.TxProcessing() txCount := len(transactions) if txCount != len(results) { return 0, 0, false @@ -140,7 +140,7 @@ func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - results = l.ledger.TxProcessing() + results = l.Ledger.TxProcessing() txCount := len(transactions) if txCount != len(results) { @@ -168,18 +168,18 @@ func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok } func getTransactionSet(l Ledger) (transactionProcessing []xdr.TransactionEnvelope) { - switch l.ledger.V { + switch l.Ledger.V { case 0: - return l.ledger.V0.TxSet.Txs + return l.Ledger.V0.TxSet.Txs case 1: - switch l.ledger.V1.TxSet.V { + switch l.Ledger.V1.TxSet.V { case 0: - return getTransactionPhase(l.ledger.V1.TxSet.V1TxSet.Phases) + return getTransactionPhase(l.Ledger.V1.TxSet.V1TxSet.Phases) default: - panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.ledger.V1.TxSet.V)) + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.Ledger.V1.TxSet.V)) } default: - panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.ledger.V)) + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.Ledger.V)) } } diff --git a/exp/xdrill/ledger_test.go b/exp/xdrill/ledger_test.go index b5ca0377a1..9c135dd21d 100644 --- a/exp/xdrill/ledger_test.go +++ b/exp/xdrill/ledger_test.go @@ -11,7 +11,7 @@ import ( func TestLedger(t *testing.T) { ledger := Ledger{ - ledger: ledgerTestInput(), + Ledger: ledgerTestInput(), } assert.Equal(t, uint32(30578981), ledger.Sequence()) From d45b0fd0b35943076ea44efa733dd95c65d0a61c Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Thu, 9 Jan 2025 19:58:42 -0500 Subject: [PATCH 6/8] Remove Ledger struct; pass lcm as param --- exp/xdrill/{ => ledger}/ledger.go | 92 ++++++++++++-------------- exp/xdrill/{ => ledger}/ledger_test.go | 49 +++++++------- 2 files changed, 67 insertions(+), 74 deletions(-) rename exp/xdrill/{ => ledger}/ledger.go (53%) rename exp/xdrill/{ => ledger}/ledger_test.go (78%) diff --git a/exp/xdrill/ledger.go b/exp/xdrill/ledger/ledger.go similarity index 53% rename from exp/xdrill/ledger.go rename to exp/xdrill/ledger/ledger.go index d794fce04a..b6cb9f9d48 100644 --- a/exp/xdrill/ledger.go +++ b/exp/xdrill/ledger/ledger.go @@ -1,4 +1,4 @@ -package xdrill +package ledger import ( "encoding/base64" @@ -9,60 +9,56 @@ import ( "github.com/stellar/go/xdr" ) -type Ledger struct { - Ledger *xdr.LedgerCloseMeta +func Sequence(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerSeq) } -func (l Ledger) Sequence() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) +func ID(l xdr.LedgerCloseMeta) int64 { + return utils.NewID(int32(l.LedgerSequence()), 0, 0).ToInt64() } -func (l Ledger) ID() int64 { - return utils.NewID(int32(l.Sequence()), 0, 0).ToInt64() +func Hash(l xdr.LedgerCloseMeta) string { + return utils.HashToHexString(l.LedgerHeaderHistoryEntry().Hash) } -func (l Ledger) Hash() string { - return utils.HashToHexString(l.Ledger.LedgerHeaderHistoryEntry().Hash) +func PreviousHash(l xdr.LedgerCloseMeta) string { + return utils.HashToHexString(l.PreviousLedgerHash()) } -func (l Ledger) PreviousHash() string { - return utils.HashToHexString(l.Ledger.PreviousLedgerHash()) +func CloseTime(l xdr.LedgerCloseMeta) int64 { + return l.LedgerCloseTime() } -func (l Ledger) CloseTime() int64 { - return l.Ledger.LedgerCloseTime() +func ClosedAt(l xdr.LedgerCloseMeta) time.Time { + return time.Unix(l.LedgerCloseTime(), 0).UTC() } -func (l Ledger) ClosedAt() time.Time { - return time.Unix(l.CloseTime(), 0).UTC() +func TotalCoins(l xdr.LedgerCloseMeta) int64 { + return int64(l.LedgerHeaderHistoryEntry().Header.TotalCoins) } -func (l Ledger) TotalCoins() int64 { - return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) +func FeePool(l xdr.LedgerCloseMeta) int64 { + return int64(l.LedgerHeaderHistoryEntry().Header.FeePool) } -func (l Ledger) FeePool() int64 { - return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.FeePool) +func BaseFee(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.BaseFee) } -func (l Ledger) BaseFee() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseFee) +func BaseReserve(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.BaseReserve) } -func (l Ledger) BaseReserve() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) +func MaxTxSetSize(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) } -func (l Ledger) MaxTxSetSize() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) +func LedgerVersion(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerVersion) } -func (l Ledger) LedgerVersion() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) -} - -func (l Ledger) SorobanFeeWrite1Kb() *int64 { - lcmV1, ok := l.Ledger.GetV1() +func SorobanFeeWrite1Kb(l xdr.LedgerCloseMeta) *int64 { + lcmV1, ok := l.GetV1() if !ok { return nil } @@ -77,8 +73,8 @@ func (l Ledger) SorobanFeeWrite1Kb() *int64 { return &result } -func (l Ledger) TotalByteSizeOfBucketList() *uint64 { - lcmV1, ok := l.Ledger.GetV1() +func TotalByteSizeOfBucketList(l xdr.LedgerCloseMeta) *uint64 { + lcmV1, ok := l.GetV1() if !ok { return nil } @@ -88,8 +84,8 @@ func (l Ledger) TotalByteSizeOfBucketList() *uint64 { return &result } -func (l Ledger) NodeID() *string { - LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() +func NodeID(l xdr.LedgerCloseMeta) *string { + LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return nil @@ -102,8 +98,8 @@ func (l Ledger) NodeID() *string { return &nodeID } -func (l Ledger) Signature() *string { - LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() +func Signature(l xdr.LedgerCloseMeta) *string { + LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return nil } @@ -114,11 +110,11 @@ func (l Ledger) Signature() *string { } // Add docstring to larger, more complicated functions -func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok bool) { +func TransactionCounts(l xdr.LedgerCloseMeta) (successTxCount, failedTxCount int32, ok bool) { var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - results = l.Ledger.TxProcessing() + results = l.TxProcessing() txCount := len(transactions) if txCount != len(results) { return 0, 0, false @@ -136,11 +132,11 @@ func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok boo } // Add docstring to larger, more complicated functions -func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok bool) { +func OperationCounts(l xdr.LedgerCloseMeta) (operationCount, txSetOperationCount int32, ok bool) { var results []xdr.TransactionResultMeta transactions := getTransactionSet(l) - results = l.Ledger.TxProcessing() + results = l.TxProcessing() txCount := len(transactions) if txCount != len(results) { @@ -167,19 +163,19 @@ func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok return operationCount, txSetOperationCount, true } -func getTransactionSet(l Ledger) (transactionProcessing []xdr.TransactionEnvelope) { - switch l.Ledger.V { +func getTransactionSet(l xdr.LedgerCloseMeta) (transactionProcessing []xdr.TransactionEnvelope) { + switch l.V { case 0: - return l.Ledger.V0.TxSet.Txs + return l.V0.TxSet.Txs case 1: - switch l.Ledger.V1.TxSet.V { + switch l.V1.TxSet.V { case 0: - return getTransactionPhase(l.Ledger.V1.TxSet.V1TxSet.Phases) + return getTransactionPhase(l.V1.TxSet.V1TxSet.Phases) default: - panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.Ledger.V1.TxSet.V)) + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.V1.TxSet.V)) } default: - panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.Ledger.V)) + panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.V)) } } diff --git a/exp/xdrill/ledger_test.go b/exp/xdrill/ledger/ledger_test.go similarity index 78% rename from exp/xdrill/ledger_test.go rename to exp/xdrill/ledger/ledger_test.go index 9c135dd21d..7adac0a4cb 100644 --- a/exp/xdrill/ledger_test.go +++ b/exp/xdrill/ledger/ledger_test.go @@ -1,4 +1,4 @@ -package xdrill +package ledger import ( "testing" @@ -10,53 +10,50 @@ import ( ) func TestLedger(t *testing.T) { - ledger := Ledger{ - Ledger: ledgerTestInput(), - } - - assert.Equal(t, uint32(30578981), ledger.Sequence()) - assert.Equal(t, int64(131335723340005376), ledger.ID()) - assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", ledger.Hash()) - assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", ledger.PreviousHash()) - assert.Equal(t, int64(1594584547), ledger.CloseTime()) - assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ledger.ClosedAt()) - assert.Equal(t, int64(1054439020873472865), ledger.TotalCoins()) - assert.Equal(t, int64(18153766209161), ledger.FeePool()) - assert.Equal(t, uint32(100), ledger.BaseFee()) - assert.Equal(t, uint32(5000000), ledger.BaseReserve()) - assert.Equal(t, uint32(1000), ledger.MaxTxSetSize()) - assert.Equal(t, uint32(13), ledger.LedgerVersion()) + ledger := ledgerTestInput() - var ok bool + assert.Equal(t, uint32(30578981), Sequence(ledger)) + assert.Equal(t, int64(131335723340005376), ID(ledger)) + assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", Hash(ledger)) + assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", PreviousHash(ledger)) + assert.Equal(t, int64(1594584547), CloseTime(ledger)) + assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ClosedAt(ledger)) + assert.Equal(t, int64(1054439020873472865), TotalCoins(ledger)) + assert.Equal(t, int64(18153766209161), FeePool(ledger)) + assert.Equal(t, uint32(100), BaseFee(ledger)) + assert.Equal(t, uint32(5000000), BaseReserve(ledger)) + assert.Equal(t, uint32(1000), MaxTxSetSize(ledger)) + assert.Equal(t, uint32(13), LedgerVersion(ledger)) - freeWrite := ledger.SorobanFeeWrite1Kb() + freeWrite := SorobanFeeWrite1Kb(ledger) assert.Equal(t, int64(12), *freeWrite) - bucketSize := ledger.TotalByteSizeOfBucketList() + bucketSize := TotalByteSizeOfBucketList(ledger) assert.Equal(t, uint64(56), *bucketSize) - nodeID := ledger.NodeID() + nodeID := NodeID(ledger) assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", *nodeID) - signature := ledger.Signature() + signature := Signature(ledger) assert.Equal(t, "9g==", *signature) + var ok bool var success int32 var failed int32 - success, failed, ok = ledger.TransactionCounts() + success, failed, ok = TransactionCounts(ledger) assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(1), failed) - success, failed, ok = ledger.OperationCounts() + success, failed, ok = OperationCounts(ledger) assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(13), failed) } -func ledgerTestInput() (lcm *xdr.LedgerCloseMeta) { - lcm = &xdr.LedgerCloseMeta{ +func ledgerTestInput() (lcm xdr.LedgerCloseMeta) { + lcm = xdr.LedgerCloseMeta{ V: 1, V1: &xdr.LedgerCloseMetaV1{ Ext: xdr.LedgerCloseMetaExt{ From 40d505759d70f72b5937f53447da774105c3bff6 Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Fri, 10 Jan 2025 14:42:51 -0700 Subject: [PATCH 7/8] Move xdrill ledger functions to ingest as subpackage --- exp/xdrill/ledger/ledger.go | 204 ------------------- exp/xdrill/utils/utils.go | 128 ------------ ingest/ledger/ledger.go | 150 ++++++++++++++ {exp/xdrill => ingest}/ledger/ledger_test.go | 99 ++++++--- xdr/node_id.go | 22 ++ 5 files changed, 244 insertions(+), 359 deletions(-) delete mode 100644 exp/xdrill/ledger/ledger.go delete mode 100644 exp/xdrill/utils/utils.go create mode 100644 ingest/ledger/ledger.go rename {exp/xdrill => ingest}/ledger/ledger_test.go (61%) create mode 100644 xdr/node_id.go diff --git a/exp/xdrill/ledger/ledger.go b/exp/xdrill/ledger/ledger.go deleted file mode 100644 index b6cb9f9d48..0000000000 --- a/exp/xdrill/ledger/ledger.go +++ /dev/null @@ -1,204 +0,0 @@ -package ledger - -import ( - "encoding/base64" - "fmt" - "time" - - "github.com/stellar/go/exp/xdrill/utils" - "github.com/stellar/go/xdr" -) - -func Sequence(l xdr.LedgerCloseMeta) uint32 { - return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerSeq) -} - -func ID(l xdr.LedgerCloseMeta) int64 { - return utils.NewID(int32(l.LedgerSequence()), 0, 0).ToInt64() -} - -func Hash(l xdr.LedgerCloseMeta) string { - return utils.HashToHexString(l.LedgerHeaderHistoryEntry().Hash) -} - -func PreviousHash(l xdr.LedgerCloseMeta) string { - return utils.HashToHexString(l.PreviousLedgerHash()) -} - -func CloseTime(l xdr.LedgerCloseMeta) int64 { - return l.LedgerCloseTime() -} - -func ClosedAt(l xdr.LedgerCloseMeta) time.Time { - return time.Unix(l.LedgerCloseTime(), 0).UTC() -} - -func TotalCoins(l xdr.LedgerCloseMeta) int64 { - return int64(l.LedgerHeaderHistoryEntry().Header.TotalCoins) -} - -func FeePool(l xdr.LedgerCloseMeta) int64 { - return int64(l.LedgerHeaderHistoryEntry().Header.FeePool) -} - -func BaseFee(l xdr.LedgerCloseMeta) uint32 { - return uint32(l.LedgerHeaderHistoryEntry().Header.BaseFee) -} - -func BaseReserve(l xdr.LedgerCloseMeta) uint32 { - return uint32(l.LedgerHeaderHistoryEntry().Header.BaseReserve) -} - -func MaxTxSetSize(l xdr.LedgerCloseMeta) uint32 { - return uint32(l.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) -} - -func LedgerVersion(l xdr.LedgerCloseMeta) uint32 { - return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerVersion) -} - -func SorobanFeeWrite1Kb(l xdr.LedgerCloseMeta) *int64 { - lcmV1, ok := l.GetV1() - if !ok { - return nil - } - - extV1, ok := lcmV1.Ext.GetV1() - if !ok { - return nil - } - - result := int64(extV1.SorobanFeeWrite1Kb) - - return &result -} - -func TotalByteSizeOfBucketList(l xdr.LedgerCloseMeta) *uint64 { - lcmV1, ok := l.GetV1() - if !ok { - return nil - } - - result := uint64(lcmV1.TotalByteSizeOfBucketList) - - return &result -} - -func NodeID(l xdr.LedgerCloseMeta) *string { - LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() - if !ok { - return nil - - } - nodeID, ok := utils.GetAddress(LedgerCloseValueSignature.NodeId) - if !ok { - return nil - } - - return &nodeID -} - -func Signature(l xdr.LedgerCloseMeta) *string { - LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() - if !ok { - return nil - } - - result := base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature) - - return &result -} - -// Add docstring to larger, more complicated functions -func TransactionCounts(l xdr.LedgerCloseMeta) (successTxCount, failedTxCount int32, ok bool) { - var results []xdr.TransactionResultMeta - - transactions := getTransactionSet(l) - results = l.TxProcessing() - 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 -} - -// Add docstring to larger, more complicated functions -func OperationCounts(l xdr.LedgerCloseMeta) (operationCount, txSetOperationCount int32, ok bool) { - var results []xdr.TransactionResultMeta - - transactions := getTransactionSet(l) - results = l.TxProcessing() - - 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 xdr.LedgerCloseMeta) (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 -} diff --git a/exp/xdrill/utils/utils.go b/exp/xdrill/utils/utils.go deleted file mode 100644 index 645967679e..0000000000 --- a/exp/xdrill/utils/utils.go +++ /dev/null @@ -1,128 +0,0 @@ -package utils - -import ( - "encoding/hex" - - "github.com/stellar/go/keypair" - "github.com/stellar/go/strkey" - "github.com/stellar/go/txnbuild" - "github.com/stellar/go/xdr" -) - -// HashToHexString is utility function that converts and xdr.Hash type to a hex string -func HashToHexString(inputHash xdr.Hash) string { - sliceHash := inputHash[:] - hexString := hex.EncodeToString(sliceHash) - return hexString -} - -type ID struct { - LedgerSequence int32 - TransactionOrder int32 - OperationOrder int32 -} - -const ( - // LedgerMask is the bitmask to mask out ledger sequences in a - // TotalOrderID - LedgerMask = (1 << 32) - 1 - // TransactionMask is the bitmask to mask out transaction indexes - TransactionMask = (1 << 20) - 1 - // OperationMask is the bitmask to mask out operation indexes - OperationMask = (1 << 12) - 1 - - // LedgerShift is the number of bits to shift an int64 to target the - // ledger component - LedgerShift = 32 - // TransactionShift is the number of bits to shift an int64 to - // target the transaction component - TransactionShift = 12 - // OperationShift is the number of bits to shift an int64 to target - // the operation component - OperationShift = 0 -) - -// New creates a new total order ID -func NewID(ledger int32, tx int32, op int32) *ID { - return &ID{ - LedgerSequence: ledger, - TransactionOrder: tx, - OperationOrder: op, - } -} - -// ToInt64 converts this struct back into an int64 -func (id ID) ToInt64() (result int64) { - - if id.LedgerSequence < 0 { - panic("invalid ledger sequence") - } - - if id.TransactionOrder > TransactionMask { - panic("transaction order overflow") - } - - if id.OperationOrder > OperationMask { - panic("operation order overflow") - } - - result = result | ((int64(id.LedgerSequence) & LedgerMask) << LedgerShift) - result = result | ((int64(id.TransactionOrder) & TransactionMask) << TransactionShift) - result = result | ((int64(id.OperationOrder) & OperationMask) << OperationShift) - return -} - -// TODO: This should be moved into the go monorepo xdr functions -// Or nodeID should just be an xdr.AccountId but the error message would be incorrect -func GetAddress(nodeID xdr.NodeId) (string, bool) { - switch nodeID.Type { - case xdr.PublicKeyTypePublicKeyTypeEd25519: - ed, ok := nodeID.GetEd25519() - if !ok { - return "", false - } - raw := make([]byte, 32) - copy(raw, ed[:]) - encodedAddress, err := strkey.Encode(strkey.VersionByteAccountID, raw) - if err != nil { - return "", false - } - return encodedAddress, true - default: - return "", false - } -} - -func CreateSampleTx(sequence int64, operationCount int) xdr.TransactionEnvelope { - kp, err := keypair.Random() - PanicOnError(err) - - operations := []txnbuild.Operation{} - operationType := &txnbuild.BumpSequence{ - BumpTo: 0, - } - for i := 0; i < operationCount; i++ { - operations = append(operations, operationType) - } - - sourceAccount := txnbuild.NewSimpleAccount(kp.Address(), int64(0)) - tx, err := txnbuild.NewTransaction( - txnbuild.TransactionParams{ - SourceAccount: &sourceAccount, - Operations: operations, - BaseFee: txnbuild.MinBaseFee, - Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, - }, - ) - PanicOnError(err) - - env := tx.ToXDR() - return env -} - -// PanicOnError is a function that panics if the provided error is not nil -func PanicOnError(err error) { - if err != nil { - panic(err) - } -} diff --git a/ingest/ledger/ledger.go b/ingest/ledger/ledger.go new file mode 100644 index 0000000000..fb58dbd9a5 --- /dev/null +++ b/ingest/ledger/ledger.go @@ -0,0 +1,150 @@ +package ledger + +import ( + "encoding/base64" + "time" + + "github.com/stellar/go/toid" + "github.com/stellar/go/xdr" +) + +type Ledger struct { + Ledger xdr.LedgerCloseMeta +} + +func (l Ledger) Sequence() uint32 { + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) +} + +func (l Ledger) ID() int64 { + return toid.New(int32(l.Ledger.LedgerSequence()), 0, 0).ToInt64() +} + +func (l Ledger) Hash() string { + return l.Ledger.LedgerHeaderHistoryEntry().Hash.HexString() +} + +func (l Ledger) PreviousHash() string { + return l.Ledger.PreviousLedgerHash().HexString() +} + +func (l Ledger) CloseTime() int64 { + return l.Ledger.LedgerCloseTime() +} + +func (l Ledger) ClosedAt() time.Time { + return time.Unix(l.Ledger.LedgerCloseTime(), 0).UTC() +} + +func (l Ledger) TotalCoins() int64 { + return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) +} + +func (l Ledger) FeePool() int64 { + return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.FeePool) +} + +func (l Ledger) BaseFee() uint32 { + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseFee) +} + +func (l Ledger) BaseReserve() uint32 { + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) +} + +func (l Ledger) MaxTxSetSize() uint32 { + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) +} + +func (l Ledger) LedgerVersion() uint32 { + return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) +} + +func (l Ledger) SorobanFeeWrite1Kb() (int64, bool) { + lcmV1, ok := l.Ledger.GetV1() + if !ok { + return 0, false + } + + extV1, ok := lcmV1.Ext.GetV1() + if !ok { + return 0, false + } + + return int64(extV1.SorobanFeeWrite1Kb), true +} + +func (l Ledger) TotalByteSizeOfBucketList() (uint64, bool) { + lcmV1, ok := l.Ledger.GetV1() + if !ok { + return 0, false + } + + return uint64(lcmV1.TotalByteSizeOfBucketList), true +} + +func (l Ledger) NodeID() (string, bool) { + LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + if !ok { + return "", false + + } + return LedgerCloseValueSignature.NodeId.GetAddress() +} + +func (l Ledger) Signature() (string, bool) { + LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() + if !ok { + return "", false + } + + return base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature), true +} + +// Add docstring to larger, more complicated functions +func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok bool) { + var results []xdr.TransactionResultMeta + + transactions := l.Ledger.TransactionEnvelopes() + results = l.Ledger.TxProcessing() + 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 +} + +// Add docstring to larger, more complicated functions +func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok bool) { + var results []xdr.TransactionResultMeta + + transactions := l.Ledger.TransactionEnvelopes() + results = l.Ledger.TxProcessing() + + for i, result := range results { + operations := transactions[i].Operations() + numberOfOps := int32(len(operations)) + txSetOperationCount += numberOfOps + + // for successful transactions, the operation count is based on the operations results slice + if result.Result.Successful() { + operationResults, ok := result.Result.OperationResults() + if !ok { + return 0, 0, false + } + + operationCount += int32(len(operationResults)) + } + } + + return operationCount, txSetOperationCount, true +} diff --git a/exp/xdrill/ledger/ledger_test.go b/ingest/ledger/ledger_test.go similarity index 61% rename from exp/xdrill/ledger/ledger_test.go rename to ingest/ledger/ledger_test.go index 7adac0a4cb..3c4b388ec8 100644 --- a/exp/xdrill/ledger/ledger_test.go +++ b/ingest/ledger/ledger_test.go @@ -4,48 +4,59 @@ import ( "testing" "time" - "github.com/stellar/go/exp/xdrill/utils" + "github.com/stellar/go/keypair" + "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" ) func TestLedger(t *testing.T) { - ledger := ledgerTestInput() + ledger := Ledger{ + Ledger: ledgerTestInput(), + } - assert.Equal(t, uint32(30578981), Sequence(ledger)) - assert.Equal(t, int64(131335723340005376), ID(ledger)) - assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", Hash(ledger)) - assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", PreviousHash(ledger)) - assert.Equal(t, int64(1594584547), CloseTime(ledger)) - assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ClosedAt(ledger)) - assert.Equal(t, int64(1054439020873472865), TotalCoins(ledger)) - assert.Equal(t, int64(18153766209161), FeePool(ledger)) - assert.Equal(t, uint32(100), BaseFee(ledger)) - assert.Equal(t, uint32(5000000), BaseReserve(ledger)) - assert.Equal(t, uint32(1000), MaxTxSetSize(ledger)) - assert.Equal(t, uint32(13), LedgerVersion(ledger)) + assert.Equal(t, uint32(30578981), ledger.Sequence()) + assert.Equal(t, int64(131335723340005376), ledger.ID()) + assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", ledger.Hash()) + assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", ledger.PreviousHash()) + assert.Equal(t, int64(1594584547), ledger.CloseTime()) + assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ledger.ClosedAt()) + assert.Equal(t, int64(1054439020873472865), ledger.TotalCoins()) + assert.Equal(t, int64(18153766209161), ledger.FeePool()) + assert.Equal(t, uint32(100), ledger.BaseFee()) + assert.Equal(t, uint32(5000000), ledger.BaseReserve()) + assert.Equal(t, uint32(1000), ledger.MaxTxSetSize()) + assert.Equal(t, uint32(13), ledger.LedgerVersion()) - freeWrite := SorobanFeeWrite1Kb(ledger) - assert.Equal(t, int64(12), *freeWrite) + var ok bool + var freeWrite int64 + freeWrite, ok = ledger.SorobanFeeWrite1Kb() + assert.Equal(t, true, ok) + assert.Equal(t, int64(12), freeWrite) - bucketSize := TotalByteSizeOfBucketList(ledger) - assert.Equal(t, uint64(56), *bucketSize) + var bucketSize uint64 + bucketSize, ok = ledger.TotalByteSizeOfBucketList() + assert.Equal(t, true, ok) + assert.Equal(t, uint64(56), bucketSize) - nodeID := NodeID(ledger) - assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", *nodeID) + var nodeID string + nodeID, ok = ledger.NodeID() + assert.Equal(t, true, ok) + assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", nodeID) - signature := Signature(ledger) - assert.Equal(t, "9g==", *signature) + var signature string + signature, ok = ledger.Signature() + assert.Equal(t, true, ok) + assert.Equal(t, "9g==", signature) - var ok bool var success int32 var failed int32 - success, failed, ok = TransactionCounts(ledger) + success, failed, ok = ledger.TransactionCounts() assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(1), failed) - success, failed, ok = OperationCounts(ledger) + success, failed, ok = ledger.OperationCounts() assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(13), failed) @@ -100,8 +111,8 @@ func ledgerTestInput() (lcm xdr.LedgerCloseMeta) { Type: 0, TxsMaybeDiscountedFee: &xdr.TxSetComponentTxsMaybeDiscountedFee{ Txs: []xdr.TransactionEnvelope{ - utils.CreateSampleTx(0, 3), - utils.CreateSampleTx(1, 10), + createSampleTx(3), + createSampleTx(10), }, }, }, @@ -157,3 +168,37 @@ func ledgerTestInput() (lcm xdr.LedgerCloseMeta) { return lcm } + +func createSampleTx(operationCount int) xdr.TransactionEnvelope { + kp, err := keypair.Random() + panicOnError(err) + + operations := []txnbuild.Operation{} + operationType := &txnbuild.BumpSequence{ + BumpTo: 0, + } + for i := 0; i < operationCount; i++ { + operations = append(operations, operationType) + } + + sourceAccount := txnbuild.NewSimpleAccount(kp.Address(), int64(0)) + tx, err := txnbuild.NewTransaction( + txnbuild.TransactionParams{ + SourceAccount: &sourceAccount, + Operations: operations, + BaseFee: txnbuild.MinBaseFee, + Preconditions: txnbuild.Preconditions{TimeBounds: txnbuild.NewInfiniteTimeout()}, + }, + ) + panicOnError(err) + + env := tx.ToXDR() + return env +} + +// PanicOnError is a function that panics if the provided error is not nil +func panicOnError(err error) { + if err != nil { + panic(err) + } +} diff --git a/xdr/node_id.go b/xdr/node_id.go new file mode 100644 index 0000000000..b3f9c77eb8 --- /dev/null +++ b/xdr/node_id.go @@ -0,0 +1,22 @@ +package xdr + +import "github.com/stellar/go/strkey" + +func (n NodeId) GetAddress() (string, bool) { + switch n.Type { + case PublicKeyTypePublicKeyTypeEd25519: + ed, ok := n.GetEd25519() + if !ok { + return "", false + } + raw := make([]byte, 32) + copy(raw, ed[:]) + encodedAddress, err := strkey.Encode(strkey.VersionByteAccountID, raw) + if err != nil { + return "", false + } + return encodedAddress, true + default: + return "", false + } +} From 89421684c4efea72386c74203e1dcbc79c5413e6 Mon Sep 17 00:00:00 2001 From: Simon Chow Date: Fri, 10 Jan 2025 15:29:16 -0700 Subject: [PATCH 8/8] Change Ledger to use lcm as param instead --- ingest/ledger/ledger.go | 80 +++++++++++++++++------------------- ingest/ledger/ledger_test.go | 43 +++++++++---------- 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/ingest/ledger/ledger.go b/ingest/ledger/ledger.go index fb58dbd9a5..c37cb50b3b 100644 --- a/ingest/ledger/ledger.go +++ b/ingest/ledger/ledger.go @@ -8,60 +8,56 @@ import ( "github.com/stellar/go/xdr" ) -type Ledger struct { - Ledger xdr.LedgerCloseMeta +func Sequence(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerSeq) } -func (l Ledger) Sequence() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerSeq) +func ID(l xdr.LedgerCloseMeta) int64 { + return toid.New(int32(l.LedgerSequence()), 0, 0).ToInt64() } -func (l Ledger) ID() int64 { - return toid.New(int32(l.Ledger.LedgerSequence()), 0, 0).ToInt64() +func Hash(l xdr.LedgerCloseMeta) string { + return l.LedgerHeaderHistoryEntry().Hash.HexString() } -func (l Ledger) Hash() string { - return l.Ledger.LedgerHeaderHistoryEntry().Hash.HexString() +func PreviousHash(l xdr.LedgerCloseMeta) string { + return l.PreviousLedgerHash().HexString() } -func (l Ledger) PreviousHash() string { - return l.Ledger.PreviousLedgerHash().HexString() +func CloseTime(l xdr.LedgerCloseMeta) int64 { + return l.LedgerCloseTime() } -func (l Ledger) CloseTime() int64 { - return l.Ledger.LedgerCloseTime() +func ClosedAt(l xdr.LedgerCloseMeta) time.Time { + return time.Unix(l.LedgerCloseTime(), 0).UTC() } -func (l Ledger) ClosedAt() time.Time { - return time.Unix(l.Ledger.LedgerCloseTime(), 0).UTC() +func TotalCoins(l xdr.LedgerCloseMeta) int64 { + return int64(l.LedgerHeaderHistoryEntry().Header.TotalCoins) } -func (l Ledger) TotalCoins() int64 { - return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.TotalCoins) +func FeePool(l xdr.LedgerCloseMeta) int64 { + return int64(l.LedgerHeaderHistoryEntry().Header.FeePool) } -func (l Ledger) FeePool() int64 { - return int64(l.Ledger.LedgerHeaderHistoryEntry().Header.FeePool) +func BaseFee(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.BaseFee) } -func (l Ledger) BaseFee() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseFee) +func BaseReserve(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.BaseReserve) } -func (l Ledger) BaseReserve() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.BaseReserve) +func MaxTxSetSize(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) } -func (l Ledger) MaxTxSetSize() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.MaxTxSetSize) +func LedgerVersion(l xdr.LedgerCloseMeta) uint32 { + return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerVersion) } -func (l Ledger) LedgerVersion() uint32 { - return uint32(l.Ledger.LedgerHeaderHistoryEntry().Header.LedgerVersion) -} - -func (l Ledger) SorobanFeeWrite1Kb() (int64, bool) { - lcmV1, ok := l.Ledger.GetV1() +func SorobanFeeWrite1Kb(l xdr.LedgerCloseMeta) (int64, bool) { + lcmV1, ok := l.GetV1() if !ok { return 0, false } @@ -74,8 +70,8 @@ func (l Ledger) SorobanFeeWrite1Kb() (int64, bool) { return int64(extV1.SorobanFeeWrite1Kb), true } -func (l Ledger) TotalByteSizeOfBucketList() (uint64, bool) { - lcmV1, ok := l.Ledger.GetV1() +func TotalByteSizeOfBucketList(l xdr.LedgerCloseMeta) (uint64, bool) { + lcmV1, ok := l.GetV1() if !ok { return 0, false } @@ -83,8 +79,8 @@ func (l Ledger) TotalByteSizeOfBucketList() (uint64, bool) { return uint64(lcmV1.TotalByteSizeOfBucketList), true } -func (l Ledger) NodeID() (string, bool) { - LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() +func NodeID(l xdr.LedgerCloseMeta) (string, bool) { + LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return "", false @@ -92,8 +88,8 @@ func (l Ledger) NodeID() (string, bool) { return LedgerCloseValueSignature.NodeId.GetAddress() } -func (l Ledger) Signature() (string, bool) { - LedgerCloseValueSignature, ok := l.Ledger.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() +func Signature(l xdr.LedgerCloseMeta) (string, bool) { + LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature() if !ok { return "", false } @@ -102,11 +98,11 @@ func (l Ledger) Signature() (string, bool) { } // Add docstring to larger, more complicated functions -func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok bool) { +func TransactionCounts(l xdr.LedgerCloseMeta) (successTxCount, failedTxCount int32, ok bool) { var results []xdr.TransactionResultMeta - transactions := l.Ledger.TransactionEnvelopes() - results = l.Ledger.TxProcessing() + transactions := l.TransactionEnvelopes() + results = l.TxProcessing() txCount := len(transactions) if txCount != len(results) { return 0, 0, false @@ -124,11 +120,11 @@ func (l Ledger) TransactionCounts() (successTxCount, failedTxCount int32, ok boo } // Add docstring to larger, more complicated functions -func (l Ledger) OperationCounts() (operationCount, txSetOperationCount int32, ok bool) { +func OperationCounts(l xdr.LedgerCloseMeta) (operationCount, txSetOperationCount int32, ok bool) { var results []xdr.TransactionResultMeta - transactions := l.Ledger.TransactionEnvelopes() - results = l.Ledger.TxProcessing() + transactions := l.TransactionEnvelopes() + results = l.TxProcessing() for i, result := range results { operations := transactions[i].Operations() diff --git a/ingest/ledger/ledger_test.go b/ingest/ledger/ledger_test.go index 3c4b388ec8..2345d46792 100644 --- a/ingest/ledger/ledger_test.go +++ b/ingest/ledger/ledger_test.go @@ -11,56 +11,53 @@ import ( ) func TestLedger(t *testing.T) { - ledger := Ledger{ - Ledger: ledgerTestInput(), - } - - assert.Equal(t, uint32(30578981), ledger.Sequence()) - assert.Equal(t, int64(131335723340005376), ledger.ID()) - assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", ledger.Hash()) - assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", ledger.PreviousHash()) - assert.Equal(t, int64(1594584547), ledger.CloseTime()) - assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ledger.ClosedAt()) - assert.Equal(t, int64(1054439020873472865), ledger.TotalCoins()) - assert.Equal(t, int64(18153766209161), ledger.FeePool()) - assert.Equal(t, uint32(100), ledger.BaseFee()) - assert.Equal(t, uint32(5000000), ledger.BaseReserve()) - assert.Equal(t, uint32(1000), ledger.MaxTxSetSize()) - assert.Equal(t, uint32(13), ledger.LedgerVersion()) + ledger := ledgerTestInput() + + assert.Equal(t, uint32(30578981), Sequence(ledger)) + assert.Equal(t, int64(131335723340005376), ID(ledger)) + assert.Equal(t, "26932dc4d84b5fabe9ae744cb43ce4c6daccf98c86a991b2a14945b1adac4d59", Hash(ledger)) + assert.Equal(t, "f63c15d0eaf48afbd751a4c4dfade54a3448053c47c5a71d622668ae0cc2a208", PreviousHash(ledger)) + assert.Equal(t, int64(1594584547), CloseTime(ledger)) + assert.Equal(t, time.Time(time.Date(2020, time.July, 12, 20, 9, 7, 0, time.UTC)), ClosedAt(ledger)) + assert.Equal(t, int64(1054439020873472865), TotalCoins(ledger)) + assert.Equal(t, int64(18153766209161), FeePool(ledger)) + assert.Equal(t, uint32(100), BaseFee(ledger)) + assert.Equal(t, uint32(5000000), BaseReserve(ledger)) + assert.Equal(t, uint32(1000), MaxTxSetSize(ledger)) + assert.Equal(t, uint32(13), LedgerVersion(ledger)) var ok bool var freeWrite int64 - freeWrite, ok = ledger.SorobanFeeWrite1Kb() + freeWrite, ok = SorobanFeeWrite1Kb(ledger) assert.Equal(t, true, ok) assert.Equal(t, int64(12), freeWrite) var bucketSize uint64 - bucketSize, ok = ledger.TotalByteSizeOfBucketList() + bucketSize, ok = TotalByteSizeOfBucketList(ledger) assert.Equal(t, true, ok) assert.Equal(t, uint64(56), bucketSize) var nodeID string - nodeID, ok = ledger.NodeID() + nodeID, ok = NodeID(ledger) assert.Equal(t, true, ok) assert.Equal(t, "GARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76O", nodeID) var signature string - signature, ok = ledger.Signature() + signature, ok = Signature(ledger) assert.Equal(t, true, ok) assert.Equal(t, "9g==", signature) var success int32 var failed int32 - success, failed, ok = ledger.TransactionCounts() + success, failed, ok = TransactionCounts(ledger) assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(1), failed) - success, failed, ok = ledger.OperationCounts() + success, failed, ok = OperationCounts(ledger) assert.Equal(t, true, ok) assert.Equal(t, int32(1), success) assert.Equal(t, int32(13), failed) - } func ledgerTestInput() (lcm xdr.LedgerCloseMeta) {