Skip to content

Commit

Permalink
Merge pull request #153 from bitcoin-sv/tone-fix-beefsort
Browse files Browse the repository at this point in the history
Tone fix beefsort
  • Loading branch information
ty-everett authored Dec 10, 2024
2 parents c77c716 + 416a42b commit 074b02e
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 48 deletions.
78 changes: 47 additions & 31 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,78 +13,80 @@ All notable changes to this project will be documented in this file. The format
- [Removed](#removed)
- [Fixed](#fixed)
- [Security](#security)
- [\[1.2.10\]](#1210)
- [Added](#added-1)
- [Fixed](#fixed-1)
- [Security](#security-1)
- [\[1.2.9\] - 2024-12-06](#129---2024-12-06)
- [\[1.2.9\] Added](#129-added)
- [\[1.2.8\] - 2024-12-02](#128---2024-12-02)
- [Fixed](#127-fixed)
- [\[1.2.8\] Fixed](#128-fixed)
- [\[1.2.7\] - 2024-12-02](#127---2024-12-02)
- [Added](#127-added)
- [Fixed](#127-fixed)
- [\[1.2.7\] Added](#127-added)
- [\[1.2.7\] Fixed](#127-fixed)
- [\[1.2.6\] - 2024-11-30](#126---2024-11-30)
- [Added](#126-fixed)
- [\[1.2.6\] Fixed](#126-fixed)
- [\[1.2.5\] - 2024-11-30](#125---2024-11-30)
- [Added](#125-added)
- [\[1.2.5\] Added](#125-added)
- [\[1.2.4\] - 2024-11-29](#124---2024-11-29)
- [Added](#124-added)
- [\[1.2.4\] Added](#124-added)
- [\[1.2.3\] - 2024-11-26](#123---2024-11-26)
- [Added](#123-added)
- [\[1.2.3\] Added](#123-added)
- [\[1.2.2\] - 2024-11-26](#122---2024-11-26)
- [Added](#122-added)
- [\[1.2.2\] Added](#122-added)
- [\[1.2.1\] - 2024-11-25](#121---2024-11-25)
- [Added](#121-added)
- [\[1.2.1\] Added](#121-added)
- [\[1.2.0\] - 2024-11-25](#120---2024-11-25)
- [Added](#120-added)
- [\[1.2.0\] Added](#120-added)
- [\[1.1.33\] - 2024-11-22](#1133---2024-11-22)
- [Added](#added-1)
- [Fixed](#fixed-1)
- [\[1.1.32\] - 2024-11-22](#1132---2024-11-22)
- [Added](#added-2)
- [Fixed](#fixed-2)
- [\[1.1.32\] - 2024-11-22](#1132---2024-11-22)
- [Added](#added-3)
- [Fixed](#fixed-3)
- [Removed](#removed-1)
- [\[1.1.30\] - 2024-11-02](#1130---2024-11-02)
- [Added](#added-3)
- [Added](#added-4)
- [Changed](#changed-1)
- [Deprecated](#deprecated-1)
- [Removed](#removed-2)
- [Fixed](#fixed-3)
- [Security](#security-1)
- [\[1.1.29\] - 2024-10-23](#1129---2024-10-23)
- [Fixed](#fixed-4)
- [\[1.1.28\] - 2024-10-23](#1128---2024-10-23)
- [Added](#added-4)
- [\[1.1.26\] - 2024-10-22](#1126---2024-10-22)
- [Added](#added-5)
- [\[1.1.25\] - 2024-10-21](#1125---2024-10-21)
- [\[1.1.26\] - 2024-10-22](#1126---2024-10-22)
- [Added](#added-6)
- [\[1.1.25\] - 2024-10-21](#1125---2024-10-21)
- [Added](#added-7)
- [\[1.1.24\] - 2024-10-04](#1124---2024-10-04)
- [Fixed](#fixed-5)
- [\[1.1.22\] - 2024-09-02](#1122---2024-09-02)
- [Added](#added-7)
- [\[1.1.21\] - 2024-09-02](#1121---2024-09-02)
- [Added](#added-8)
- [\[1.1.21\] - 2024-09-02](#1121---2024-09-02)
- [Added](#added-9)
- [Changed](#changed-2)
- [\[1.1.17\] - 2024-08-21](#1117---2024-08-21)
- [Added](#added-9)
- [\[1.1.14\] - 2024-07-30](#1114---2024-07-30)
- [Added](#added-10)
- [\[1.1.14\] - 2024-07-30](#1114---2024-07-30)
- [Added](#added-11)
- [\[1.1.13\] - 2024-07-19](#1113---2024-07-19)
- [Fixed](#fixed-6)
- [\[1.1.10\] - 2024-06-28](#1110---2024-06-28)
- [Fixed](#fixed-7)
- [\[1.1.8\] - 2024-06-19](#118---2024-06-19)
- [Added](#added-11)
- [\[1.1.6\] - 2024-06-12](#116---2024-06-12)
- [Added](#added-12)
- [\[1.1.6\] - 2024-06-12](#116---2024-06-12)
- [Added](#added-13)
- [\[1.1.5\] - 2024-06-11](#115---2024-06-11)
- [Fixed](#fixed-8)
- [\[1.1.4\] - 2024-05-10](#114---2024-05-10)
- [Added](#added-13)
- [Added](#added-14)
- [Changed](#changed-3)
- [\[1.1.0\] - 2024-05-06](#110---2024-05-06)
- [Added](#added-14)
- [Removed](#removed-3)
- [Added](#added-15)
- [Removed](#removed-2)
- [Fixed](#fixed-9)
- [New Contributors](#new-contributors)
- [\[1.0.0\] - 2024-02-10](#100---2024-02-10)
- [Added](#added-15)
- [Added](#added-16)
- [Template for New Releases:](#template-for-new-releases)

## [Unreleased]
Expand All @@ -103,6 +105,20 @@ All notable changes to this project will be documented in this file. The format

---

## [1.2.10]

### Added

Beef makeTxidOnly

### Fixed

Beef sortTx fix for partially valid and txidOnly data.

### Security

---

## [1.2.9] - 2024-12-06

### [1.2.9] Added
Expand Down
20 changes: 19 additions & 1 deletion docs/transaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export class Beef {
constructor(version?: BeefVersion)
get magic(): number
findTxid(txid: string): BeefTx | undefined
makeTxidOnly(txid: string): BeefTx | undefined
findBump(txid: string): MerklePath | undefined
findTransactionForSigning(txid: string): Transaction | undefined
findAtomicTransaction(txid: string): Transaction | undefined
Expand Down Expand Up @@ -779,6 +780,23 @@ Argument Details
+ **allowTxidOnly**
+ optional. If true, transaction txid only is assumed valid

#### Method makeTxidOnly

Replaces `BeefTx` for this txid with txidOnly.

Replacement is done so that a `clone()` can be
updated by this method without affecting the
original.

```ts
makeTxidOnly(txid: string): BeefTx | undefined
```
See also: [BeefTx](#class-beeftx)

Returns

undefined if txid is unknown.

#### Method mergeBump

Merge a MerklePath that is assumed to be fully valid.
Expand Down Expand Up @@ -847,7 +865,7 @@ Argument Details
#### Method sortTxs

Sort the `txs` by input txid dependency order:
- Oldest Tx Anchored by Path
- Oldest Tx Anchored by Path or txid only
- Newer Txs depending on Older parents
- Newest Tx

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bsv/sdk",
"version": "1.2.9",
"version": "1.2.10",
"type": "module",
"description": "BSV Blockchain Software Development Kit",
"main": "dist/cjs/mod.js",
Expand Down
52 changes: 39 additions & 13 deletions src/transaction/Beef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ export class Beef {
return this.txs.find(tx => tx.txid === txid)
}

/**
* Replaces `BeefTx` for this txid with txidOnly.
*
* Replacement is done so that a `clone()` can be
* updated by this method without affecting the
* original.
*
* @param txid
* @returns undefined if txid is unknown.
*/
makeTxidOnly (txid: string): BeefTx | undefined {
const i = this.txs.findIndex(tx => tx.txid === txid)
if (i === -1) return undefined
let btx = this.txs[i]
if (btx.isTxidOnly) { return btx }
this.txs.slice(i, i + 1)
btx = this.mergeTxidOnly(txid)
return btx
}

/**
* @returns `MerklePath` with level zero hash equal to txid or undefined.
*/
Expand Down Expand Up @@ -518,7 +538,7 @@ export class Beef {

/**
* Sort the `txs` by input txid dependency order:
* - Oldest Tx Anchored by Path
* - Oldest Tx Anchored by Path or txid only
* - Newer Txs depending on Older parents
* - Newest Tx
*
Expand Down Expand Up @@ -553,7 +573,10 @@ export class Beef {
if (tx.isValid) {
validTxids[tx.txid] = true
result.push(tx)
} else if (tx.isTxidOnly) { txidOnly.push(tx) } else { queue.push(tx) }
} else if (tx.isTxidOnly && tx.inputTxids.length === 0) {
validTxids[tx.txid] = true
txidOnly.push(tx)
} else { queue.push(tx) }
}

// Hashtable of unknown input txids used to fund transactions without their own proof.
Expand All @@ -564,17 +587,18 @@ export class Beef {
const possiblyMissingInputs = queue
queue = []

// all tx are isValid false, hasProof false.
// if isTxidOnly then has inputTxids
for (const tx of possiblyMissingInputs) {
let hasMissingInput = false
if (!tx.isValid) {
// For all the unproven transactions,
// link their inputs that exist in this beef,
// make a note of missing inputs.
for (const inputTxid of tx.inputTxids) {
if (!txidToTx[inputTxid]) {
missingInputs[inputTxid] = true
hasMissingInput = true
}

// For all the unproven transactions,
// link their inputs that exist in this beef,
// make a note of missing inputs.
for (const inputTxid of tx.inputTxids) {
if (!txidToTx[inputTxid]) {
missingInputs[inputTxid] = true
hasMissingInput = true
}
}
if (hasMissingInput) { txsMissingInputs.push(tx) } else { queue.push(tx) }
Expand All @@ -584,6 +608,8 @@ export class Beef {
while (queue.length > 0) {
const oldQueue = queue
queue = []
// all tx are isValid false, hasProof false.
// if isTxidOnly then has inputTxids
for (const tx of oldQueue) {
if (tx.inputTxids.every(txid => validTxids[txid])) {
validTxids[tx.txid] = true
Expand All @@ -596,8 +622,8 @@ export class Beef {
// transactions that don't have proofs and don't chain to proofs
const txsNotValid = queue

// New order of txs is sorted, unsortable, txidOnly (no raw transaction)
this.txs = result.concat(queue).concat(txidOnly).concat(txsMissingInputs)
// New order of txs is unsortable (missing inputs or depends on missing inputs), txidOnly, sorted (so newest sorted is last)
this.txs = txsMissingInputs.concat(txsNotValid).concat(txidOnly).concat(result)

return {
missingInputs: Object.keys(missingInputs),
Expand Down
18 changes: 18 additions & 0 deletions src/transaction/__tests/Beef.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,24 @@ describe('Beef tests', () => {
expect(atomic).toEqual(beef2)
}
})
test('9_sortTxs', async () => {
{
const beef = new Beef()
beef.mergeTxidOnly('a')
const btx = beef.mergeTxidOnly('b')
btx.inputTxids = ['a']
beef.sortTxs()
expect(beef.txs[1].txid).toBe('b')
}
{
const beef = new Beef()
const atx = beef.mergeTxidOnly('a')
const btx = beef.mergeTxidOnly('b')
atx.inputTxids = ['b']
beef.sortTxs()
expect(beef.txs[1].txid).toBe('a')
}
})
})

const txs: string[] = [
Expand Down

0 comments on commit 074b02e

Please sign in to comment.