Skip to content

Commit

Permalink
Add .invalidBlockVersion error that can now be thrown by rust FFI's (
Browse files Browse the repository at this point in the history
…#178)

* remove empty specs

* Update TransactionBuilder code paths to throw error if the blockversion is invalid (to new for rust-lib).

* revert gemfile change

* point to release/v2

* update commit hash

* fix unit test after rebase

* revert version change to match cicd ?

* Fix Receipt tests

Co-authored-by: Cary A. Bakker <cary@mobilecoin.com>
  • Loading branch information
the-real-adammork and Cary A. Bakker committed Aug 29, 2022
1 parent 8604b79 commit dabfa27
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,4 @@ DEPENDENCIES
jazzy!

BUNDLED WITH
2.2.24
2.2.20
1 change: 1 addition & 0 deletions Sources/Ledger/BlockVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extension BlockVersion {
static let versionZero: BlockVersion = 0
static let versionOne: BlockVersion = 1
static let versionTwo: BlockVersion = 2
static let versionMax: BlockVersion = UInt32.max

static func canEnableRecoverableMemos(version: BlockVersion) -> Bool {
version >= versionOne
Expand Down
60 changes: 45 additions & 15 deletions Sources/Transaction/TransactionBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import LibMobileCoin

enum TransactionBuilderError: Error {
case invalidInput(String)
case invalidBlockVersion(String)
case attestationVerificationFailed(String)
}

Expand All @@ -19,6 +20,8 @@ extension TransactionBuilderError: CustomStringConvertible {
switch self {
case .invalidInput(let reason):
return "Invalid input: \(reason)"
case .invalidBlockVersion(let reason):
return "Invalid Block Version: \(reason)"
case .attestationVerificationFailed(let reason):
return "Attestation verification failed: \(reason)"
}
Expand All @@ -39,24 +42,35 @@ final class TransactionBuilder {
fogResolver: FogResolver = FogResolver(),
memoBuilder: TxOutMemoBuilder = DefaultMemoBuilder(),
blockVersion: BlockVersion
) {
) throws {
self.tombstoneBlockIndex = tombstoneBlockIndex
self.memoBuilder = memoBuilder
self.ptr = memoBuilder.withUnsafeOpaquePointer { memoBuilderPtr in
let result: Result<OpaquePointer, TransactionBuilderError>
result = memoBuilder.withUnsafeOpaquePointer { memoBuilderPtr in
fogResolver.withUnsafeOpaquePointer { fogResolverPtr in
// Safety: mc_transaction_builder_create should never return nil.
withMcInfallible {
withMcError { errorPtr in
mc_transaction_builder_create(
fee.value,
fee.tokenId.value,
tombstoneBlockIndex,
fogResolverPtr,
memoBuilderPtr,
blockVersion,
nil)
&errorPtr)
}.mapError {
switch $0.errorCode {
case .invalidInput:
return .invalidBlockVersion("\(redacting: $0.description)")
default:
// Safety: mc_transaction_builder_add_input should not throw
// non-documented errors.
logger.fatalError("Unhandled LibMobileCoin error: \(redacting: $0)")
}
}
}
}
self.ptr = try result.get()
}

deinit {
Expand Down Expand Up @@ -169,12 +183,20 @@ extension TransactionBuilder {
return .failure(.invalidInput("Input values != output values + fee"))
}

let builder = TransactionBuilder(
fee: fee,
tombstoneBlockIndex: tombstoneBlockIndex,
fogResolver: fogResolver,
memoBuilder: memoType.createMemoBuilder(accountKey: accountKey),
blockVersion: blockVersion)
let builder: TransactionBuilder
do {
builder = try TransactionBuilder(
fee: fee,
tombstoneBlockIndex: tombstoneBlockIndex,
fogResolver: fogResolver,
memoBuilder: memoType.createMemoBuilder(accountKey: accountKey),
blockVersion: blockVersion)
} catch {
guard let error = error as? TransactionBuilderError else {
return .failure(.invalidInput("Unknown Error"))
}
return .failure(error)
}

for input in inputs {
if case .failure(let error) =
Expand Down Expand Up @@ -259,11 +281,19 @@ extension TransactionBuilder {
blockVersion: BlockVersion,
rng: MobileCoinRng
) -> Result<TxOutContext, TransactionBuilderError> {
let transactionBuilder = TransactionBuilder(
fee: Amount(value: 0, tokenId: .MOB),
tombstoneBlockIndex: tombstoneBlockIndex,
fogResolver: fogResolver,
blockVersion: blockVersion)
let transactionBuilder: TransactionBuilder
do {
transactionBuilder = try TransactionBuilder(
fee: Amount(value: 0, tokenId: .MOB),
tombstoneBlockIndex: tombstoneBlockIndex,
fogResolver: fogResolver,
blockVersion: blockVersion)
} catch {
guard let error = error as? TransactionBuilderError else {
return .failure(.invalidInput("Unknown Error"))
}
return .failure(error)
}
return transactionBuilder.addOutput(
publicAddress: publicAddress,
amount: amount,
Expand Down
14 changes: 14 additions & 0 deletions Tests/Unit/Transaction/TransactionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ class TransactionTests: XCTestCase {
}
}

func testFutureBlockVersionFailure() throws {
let fixture = try Transaction.Fixtures.BuildTx()
XCTAssertFailure(TransactionBuilder.build(
inputs: fixture.inputs,
accountKey: fixture.accountKey,
outputs: fixture.outputs,
memoType: .unused,
fee: fixture.fee,
tombstoneBlockIndex: fixture.tombstoneBlockIndex,
fogResolver: fixture.fogResolver,
blockVersion: .versionMax,
rng: TestRng()))
}

func testExactChangeCreatesChangeOutput() throws {
let fixture = try Transaction.Fixtures.ExactChange()

Expand Down
2 changes: 1 addition & 1 deletion Vendor/libmobilecoin-ios-artifacts

0 comments on commit dabfa27

Please sign in to comment.