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
18 changes: 15 additions & 3 deletions Sources/blocks/Domain/Block.swift
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,21 @@ public struct Block {
Add Booker Fee Transaction into Block.
*/
if self.transactions.count <= Block.maxTransactionsInABlock {
if let signer = node.signer(), let publicKeyAsBase64String = signer.publicKeyForSignature?.rawRepresentation.base64String, let publicKey = publicKeyAsBase64String as? PublicKey {
let claimObject = ClaimOnPay.Object(destination: "")
if let bookerFeeTransaction = TransactionType.pay.construct(claim: ClaimOnPay.bookerFee, claimObject: claimObject, makerDhtAddressAsHexString: self.maker, publicKey: publicKey, book: node.book, signer: signer, peerSigner: signer, creditOnRight: ClaimOnPay.bookerFee.fee),
if let signer = node.signer(), let publicKey = signer.publicKeyAsData {
let claimObject = ClaimOnPay.Object(destination: self.maker)
if let bookerFeeTransaction = TransactionType.pay.construct(
claim: ClaimOnPay.bookerFee,
claimObject: claimObject,
makerDhtAddressAsHexString: self.maker,
publicKey: publicKey,
book: node.book,
signer: signer,
peerSigner: signer,
debitOnLeft: ClaimOnPay.bookerFee.fee,
creditOnRight: ClaimOnPay.bookerFee.fee,
withdrawalDhtAddressOnLeft: Signer.moneySupplyUnMoverAccount,
depositDhtAddressOnRight: self.maker.toString
),
let bookerFeeTransactionSignature = bookerFeeTransaction.signature,
let transactionId = bookerFeeTransaction.transactionId,
let bookerFeeTransactionPublicKey = bookerFeeTransaction.publicKey,
Expand Down
24 changes: 24 additions & 0 deletions Sources/blocks/Domain/Transaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,15 @@ public extension Transaction {
/*
Check Account Balance.
*/
if self.isCreditCreation {
guard self.isAllowedCreditCreationClaim else {
Log("Invalid Claim for Credit Creation Transaction.")
return false
}
Log("Credit Creation Transaction skips maker balance check.")
return true
}

//transactionの送金金額+手数料 <= balance
Log()
let balancedAmount = self.book.balance(dhtAddressAsHexString: self.makerDhtAddressAsHexString)
Expand Down Expand Up @@ -483,6 +492,21 @@ public extension Transaction {
return (false, nil)
}

var isCreditCreation: Bool {
self.withdrawalDhtAddressOnLeft.equal(Signer.moneySupplyUnMoverAccount)
}

var isAllowedCreditCreationClaim: Bool {
switch self.claim.rawValue {
case ClaimOnPay.bookerFee.rawValue,
ClaimOnPerson.demandBasicIncome.rawValue,
ClaimOnPerson.born.rawValue:
return true
default:
return false
}
}

// static func == (lhs: any Transaction, rhs: any Transaction) -> Bool {
static func == (lhs: Self, rhs: Self) -> Bool {
guard let lhsTransactionId = lhs.transactionId, let rhsTransactionId = rhs.transactionId else {
Expand Down
62 changes: 62 additions & 0 deletions Tests/blocksTests/CreditCreationValidationTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// CreditCreationValidationTest.swift
// blocksTests
//
// Created by Codex on 2026/05/24.
//

import XCTest
@testable import blocks
import overlayNetwork

final class CreditCreationValidationTest: XCTestCase {

func testBookerFeeCreditCreationValidatesWithoutExistingBalance() throws {
let signer = Signer(newPrivateKeyOn: "booker-account" as OverlayNetworkAddressAsHexString)
guard let publicKey = signer.publicKeyAsData else {
XCTFail("Signer should have a public key.")
return
}
let fee = ClaimOnPay.bookerFee.fee
let transaction = Pay(
claim: ClaimOnPay.bookerFee,
claimObject: ClaimOnPay.Object(destination: "booker-account"),
makerDhtAddressAsHexString: "booker-account",
publicKey: publicKey,
book: Book(signature: Data.DataNull),
signer: signer,
transactionId: "BK-booker-fee",
date: Date(timeIntervalSince1970: 1_700_000_000),
debitOnLeft: fee,
creditOnRight: fee,
withdrawalDhtAddressOnLeft: Signer.moneySupplyUnMoverAccount,
depositDhtAddressOnRight: "booker-account"
)

XCTAssertTrue(transaction.validate(branchChainHash: nil, indexInBranchChain: nil))
}

func testRegularTransactionStillRequiresExistingBalance() throws {
let signer = Signer(newPrivateKeyOn: "maker-account" as OverlayNetworkAddressAsHexString)
guard let publicKey = signer.publicKeyAsData else {
XCTFail("Signer should have a public key.")
return
}
let transaction = Pay(
claim: ClaimOnPay.bookerFee,
claimObject: ClaimOnPay.Object(destination: "deposit-account"),
makerDhtAddressAsHexString: "maker-account",
publicKey: publicKey,
book: Book(signature: Data.DataNull),
signer: signer,
transactionId: "BK-regular-payment",
date: Date(timeIntervalSince1970: 1_700_000_000),
debitOnLeft: Decimal(10),
creditOnRight: Decimal(10),
withdrawalDhtAddressOnLeft: "maker-account",
depositDhtAddressOnRight: "deposit-account"
)

XCTAssertFalse(transaction.validate(branchChainHash: nil, indexInBranchChain: nil))
}
}