diff --git a/.cargo/config.toml b/.cargo/config.toml index 2d4363c27..9a327149a 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,3 +6,6 @@ FIXTURES_TX = "fixtures/transaction" FIXTURES_VECTOR = "fixtures/vector" FIXTURES_MODELS = "fixtures/models" FIXTURES_MODELS_GW = "fixtures/models/gateway" +FIXTURES_MODELS_INTERACTION = "fixtures/models/interaction" +FIXTURES_MODELS_PROFILES = "fixtures/models/profile" +FIXTURES_MODELS_PROFILE = "fixtures/models/profile_submodels" diff --git a/Cargo.lock b/Cargo.lock index 08616da26..d68c5eb31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "account-for-display" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "derive_more", @@ -49,10 +49,10 @@ dependencies = [ [[package]] name = "addresses" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", - "bytes 1.1.122", + "bytes 1.1.123", "cap26-models", "core-utils", "derive_more", @@ -246,7 +246,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert-json" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json-diff", "error", @@ -546,7 +546,7 @@ dependencies = [ [[package]] name = "build-info" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "cargo_toml", @@ -573,7 +573,7 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytes" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "delegate", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "cap26-models" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "derive_more", @@ -748,7 +748,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clients" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-trait", @@ -808,7 +808,7 @@ checksum = "0d8a42181e0652c2997ae4d217f25b63c5337a52fd2279736e97b832fa0a3cff" [[package]] name = "core-collections" -version = "1.1.122" +version = "1.1.123" dependencies = [ "has-sample-values", "indexmap 2.7.0", @@ -835,7 +835,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-misc" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "core-utils", @@ -855,7 +855,7 @@ dependencies = [ [[package]] name = "core-utils" -version = "1.1.122" +version = "1.1.123" dependencies = [ "error", "iso8601-timestamp", @@ -1084,7 +1084,7 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "drivers" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -1108,10 +1108,10 @@ dependencies = [ [[package]] name = "ecc" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", - "bytes 1.1.122", + "bytes 1.1.123", "derive_more", "enum-as-inner", "error", @@ -1210,11 +1210,11 @@ dependencies = [ [[package]] name = "encryption" -version = "1.1.122" +version = "1.1.123" dependencies = [ "aes-gcm", "assert-json", - "bytes 1.1.122", + "bytes 1.1.123", "derive_more", "error", "has-sample-values", @@ -1231,7 +1231,7 @@ dependencies = [ [[package]] name = "entity-by-address" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "error", @@ -1243,7 +1243,7 @@ dependencies = [ [[package]] name = "entity-foundation" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "derive_more", @@ -1318,7 +1318,7 @@ dependencies = [ [[package]] name = "error" -version = "1.1.122" +version = "1.1.123" dependencies = [ "derive_more", "log", @@ -1377,7 +1377,7 @@ dependencies = [ [[package]] name = "factor-instances-provider" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -1403,9 +1403,9 @@ dependencies = [ [[package]] name = "factors" -version = "1.1.122" +version = "1.1.123" dependencies = [ - "bytes 1.1.122", + "bytes 1.1.123", "cap26-models", "core-collections", "core-misc", @@ -1440,7 +1440,7 @@ dependencies = [ [[package]] name = "factors-supporting-types" -version = "1.1.122" +version = "1.1.123" dependencies = [ "async-trait", "error", @@ -1593,7 +1593,7 @@ dependencies = [ [[package]] name = "gateway-client-and-api" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -1613,7 +1613,7 @@ dependencies = [ [[package]] name = "gateway-models" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "assert-json", @@ -1718,7 +1718,7 @@ dependencies = [ [[package]] name = "has-sample-values" -version = "1.1.122" +version = "1.1.123" dependencies = [ "error", "indexmap 2.7.0", @@ -1729,9 +1729,9 @@ dependencies = [ [[package]] name = "hash" -version = "1.1.122" +version = "1.1.123" dependencies = [ - "bytes 1.1.122", + "bytes 1.1.123", "derive_more", "prelude", "radix-common", @@ -1795,11 +1795,11 @@ dependencies = [ [[package]] name = "hierarchical-deterministic" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "bip39", - "bytes 1.1.122", + "bytes 1.1.123", "cap26-models", "derive_more", "ecc", @@ -1842,13 +1842,13 @@ dependencies = [ [[package]] name = "home-cards" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", "async-trait", "base64", - "bytes 1.1.122", + "bytes 1.1.123", "core-utils", "derive_more", "drivers", @@ -1868,7 +1868,7 @@ dependencies = [ [[package]] name = "host-info" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "derive_more", @@ -1915,10 +1915,10 @@ dependencies = [ [[package]] name = "http-client" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", - "bytes 1.1.122", + "bytes 1.1.123", "core-utils", "drivers", "error", @@ -2143,7 +2143,7 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "identified-vec-of" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "derive_more", @@ -2216,7 +2216,7 @@ dependencies = [ [[package]] name = "interactors" -version = "1.1.122" +version = "1.1.123" dependencies = [ "async-trait", "derive_more", @@ -2336,7 +2336,7 @@ dependencies = [ [[package]] name = "key-derivation-traits" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "async-trait", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "keys-collector" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -2443,7 +2443,7 @@ dependencies = [ [[package]] name = "manifests" -version = "1.1.122" +version = "1.1.123" dependencies = [ "account-for-display", "addresses", @@ -2451,6 +2451,7 @@ dependencies = [ "core-utils", "derive_more", "enum-as-inner", + "enum-iterator", "factors", "gateway-models", "hierarchical-deterministic", @@ -2484,7 +2485,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "metadata" -version = "1.1.122" +version = "1.1.123" dependencies = [ "derive_more", "has-sample-values", @@ -2584,7 +2585,7 @@ dependencies = [ [[package]] name = "network" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", "enum-iterator", @@ -2600,7 +2601,7 @@ dependencies = [ [[package]] name = "next-derivation-index-ephemeral" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "assert-json", @@ -2676,9 +2677,9 @@ dependencies = [ [[package]] name = "numeric" -version = "1.1.122" +version = "1.1.123" dependencies = [ - "bytes 1.1.122", + "bytes 1.1.123", "delegate", "derive_more", "enum-iterator", @@ -2898,7 +2899,7 @@ dependencies = [ [[package]] name = "prelude" -version = "1.1.122" +version = "1.1.123" dependencies = [ "radix-engine", "radix-engine-toolkit", @@ -2935,7 +2936,7 @@ dependencies = [ [[package]] name = "profile" -version = "1.1.122" +version = "1.1.123" dependencies = [ "account-for-display", "addresses", @@ -2979,7 +2980,7 @@ dependencies = [ [[package]] name = "profile-account" -version = "1.1.122" +version = "1.1.123" dependencies = [ "account-for-display", "addresses", @@ -2999,7 +3000,7 @@ dependencies = [ [[package]] name = "profile-account-or-persona" -version = "1.1.122" +version = "1.1.123" dependencies = [ "cap26-models", "derive_more", @@ -3016,7 +3017,7 @@ dependencies = [ [[package]] name = "profile-app-preferences" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "core-misc", @@ -3039,7 +3040,7 @@ dependencies = [ [[package]] name = "profile-base-entity" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "derive_more", @@ -3062,7 +3063,7 @@ dependencies = [ [[package]] name = "profile-gateway" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "assert-json", @@ -3086,7 +3087,7 @@ dependencies = [ [[package]] name = "profile-logic" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "derive_more", @@ -3108,7 +3109,7 @@ dependencies = [ [[package]] name = "profile-persona" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "cap26-models", @@ -3129,7 +3130,7 @@ dependencies = [ [[package]] name = "profile-persona-data" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "assert-json", @@ -3148,7 +3149,7 @@ dependencies = [ [[package]] name = "profile-security-structures" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "cap26-models", @@ -3176,7 +3177,7 @@ dependencies = [ [[package]] name = "profile-state-holder" -version = "1.1.122" +version = "1.1.123" dependencies = [ "derive_more", "error", @@ -3191,7 +3192,7 @@ dependencies = [ [[package]] name = "profile-supporting-types" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "derive_more", @@ -3280,14 +3281,14 @@ dependencies = [ [[package]] name = "radix-connect" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", "assert-json", "async-trait", "base64", - "bytes 1.1.122", + "bytes 1.1.123", "core-misc", "core-utils", "derive_more", @@ -3304,6 +3305,7 @@ dependencies = [ "prelude", "pretty_assertions", "profile-persona-data", + "profile-security-structures", "radix-connect-models", "serde", "serde_json", @@ -3315,10 +3317,10 @@ dependencies = [ [[package]] name = "radix-connect-models" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", - "bytes 1.1.122", + "bytes 1.1.123", "core-misc", "derive_more", "error", @@ -3760,7 +3762,7 @@ dependencies = [ [[package]] name = "sargon" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -3825,7 +3827,7 @@ dependencies = [ [[package]] name = "sargon-os" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-trait", @@ -3852,7 +3854,7 @@ dependencies = [ [[package]] name = "sargon-os-accounts" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -3875,7 +3877,7 @@ dependencies = [ [[package]] name = "sargon-os-derive-public-keys" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-trait", @@ -3894,7 +3896,7 @@ dependencies = [ [[package]] name = "sargon-os-factors" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-trait", @@ -3922,7 +3924,7 @@ dependencies = [ [[package]] name = "sargon-os-security-center" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "derive_more", @@ -3938,7 +3940,7 @@ dependencies = [ [[package]] name = "sargon-os-signing" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-trait", @@ -3964,7 +3966,7 @@ dependencies = [ [[package]] name = "sargon-os-transaction" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "async-std", @@ -3993,7 +3995,7 @@ dependencies = [ [[package]] name = "sargon-uniffi" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", @@ -4050,7 +4052,7 @@ dependencies = [ [[package]] name = "sargon-uniffi-conversion-macros" -version = "1.1.122" +version = "1.1.123" dependencies = [ "proc-macro2", "quote", @@ -4223,7 +4225,7 @@ dependencies = [ [[package]] name = "security-center" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", "assert-json", @@ -4391,7 +4393,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "short-string" -version = "1.1.122" +version = "1.1.123" dependencies = [ "arraystring", "assert-json", @@ -4426,13 +4428,13 @@ dependencies = [ [[package]] name = "signatures-collector" -version = "1.1.122" +version = "1.1.123" dependencies = [ "actix-rt", "addresses", "assert-json", "async-trait", - "bytes 1.1.122", + "bytes 1.1.123", "cap26-models", "core-collections", "core-misc", @@ -4464,10 +4466,10 @@ dependencies = [ [[package]] name = "signing-traits" -version = "1.1.122" +version = "1.1.123" dependencies = [ "async-trait", - "bytes 1.1.122", + "bytes 1.1.123", "core-collections", "derive_more", "ecc", @@ -4632,7 +4634,7 @@ dependencies = [ [[package]] name = "sub-systems" -version = "1.1.122" +version = "1.1.123" dependencies = [ "derive_more", "drivers", @@ -4791,7 +4793,7 @@ dependencies = [ [[package]] name = "time-utils" -version = "1.1.122" +version = "1.1.123" dependencies = [ "iso8601-timestamp", "prelude", @@ -4941,10 +4943,10 @@ dependencies = [ [[package]] name = "transaction-foundation" -version = "1.1.122" +version = "1.1.123" dependencies = [ "assert-json", - "bytes 1.1.122", + "bytes 1.1.123", "derive_more", "has-sample-values", "paste", @@ -4956,10 +4958,10 @@ dependencies = [ [[package]] name = "transaction-models" -version = "1.1.122" +version = "1.1.123" dependencies = [ "addresses", - "bytes 1.1.122", + "bytes 1.1.123", "cargo_toml", "core-collections", "core-misc", diff --git a/apple/Sources/Sargon/Drivers/FileSystem/FileSystemDriver+Data+ContentsOf+URL.swift b/apple/Sources/Sargon/Drivers/FileSystem/FileSystemDriver+Data+ContentsOf+URL.swift index c4dd11d74..ec2f4b9aa 100644 --- a/apple/Sources/Sargon/Drivers/FileSystem/FileSystemDriver+Data+ContentsOf+URL.swift +++ b/apple/Sources/Sargon/Drivers/FileSystem/FileSystemDriver+Data+ContentsOf+URL.swift @@ -2,7 +2,7 @@ import Foundation import SargonUniFFI // MARK: - FileManager + @unchecked Sendable -extension FileManager: @unchecked Sendable {} +extension FileManager: @unchecked @retroactive Sendable {} // Makes it possible to type `.shared` on an initalizer/func taking // `some FileSystemDriver` as parameter. diff --git a/apple/Sources/Sargon/Drivers/UnsafeStorage/UnsafeStorageDriver+UserDefaults.swift b/apple/Sources/Sargon/Drivers/UnsafeStorage/UnsafeStorageDriver+UserDefaults.swift index 497e6a90a..eabb4f0e3 100644 --- a/apple/Sources/Sargon/Drivers/UnsafeStorage/UnsafeStorageDriver+UserDefaults.swift +++ b/apple/Sources/Sargon/Drivers/UnsafeStorage/UnsafeStorageDriver+UserDefaults.swift @@ -2,7 +2,7 @@ import Foundation import SargonUniFFI // MARK: - UserDefaults + @unchecked Sendable -extension UserDefaults: @unchecked Sendable {} +extension UserDefaults: @unchecked @retroactive Sendable {} // Makes it possible to type `.shared` on an initalizer/func taking // `some UnsafeStorageDriver` as parameter. diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/MFA/SecurityShieldBuilder+Swifified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/MFA/SecurityShieldBuilder+Swifified.swift index a82b1d474..696d17aa5 100644 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/MFA/SecurityShieldBuilder+Swifified.swift +++ b/apple/Sources/Sargon/Extensions/Swiftified/Profile/MFA/SecurityShieldBuilder+Swifified.swift @@ -4,8 +4,8 @@ extension SecurityShieldBuilder { public typealias Factor = FactorSourceID /// Confirmation Role - public var timePeriodUntilAutoConfirm: TimePeriod { - getTimePeriodUntilAutoConfirm() + public var timeUntilTimedConfirmationIsCallable: TimePeriod { + getTimeUntilTimedConfirmationIsCallable() } public var threshold: Threshold { diff --git a/apple/Sources/Sargon/Protocols/EntityProtocol.swift b/apple/Sources/Sargon/Protocols/EntityProtocol.swift index 8c151dda3..83e3ceb8a 100644 --- a/apple/Sources/Sargon/Protocols/EntityProtocol.swift +++ b/apple/Sources/Sargon/Protocols/EntityProtocol.swift @@ -43,7 +43,6 @@ extension EntityBaseProtocol { flags.contains(.hiddenByUser) } - // TODO: MOVE TO SARGON public var virtualHierarchicalDeterministicFactorInstances: Set { @@ -55,15 +54,13 @@ extension EntityBaseProtocol { } } - // TODO: MOVE TO SARGON public var hasAuthenticationSigningKey: Bool { switch securityState { - case let .unsecured(unsecuredEntityControl): + case .unsecured: false } } - // TODO: MOVE TO SARGON public var deviceFactorSourceID: FactorSourceIDFromHash? { switch self.securityState { case let .unsecured(control): diff --git a/apple/Tests/IntegrationTests/SargonOS/TestOSTests.swift b/apple/Tests/IntegrationTests/SargonOS/TestOSTests.swift index 7b28a3ac3..9613eef61 100644 --- a/apple/Tests/IntegrationTests/SargonOS/TestOSTests.swift +++ b/apple/Tests/IntegrationTests/SargonOS/TestOSTests.swift @@ -113,6 +113,7 @@ final class TestOSTests: OSTest { XCTAssertEqual(try sut.os.profile().header.creatingDevice, newCreatingDevice) // assert change worked } + @available(*, deprecated) func batch_create_many_accounts() async throws { let sut = await TestOS() try await sut.os.newWallet(shouldPreDeriveInstances: false) diff --git a/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift b/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift index fa3d706ec..c31a88b76 100644 --- a/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift @@ -18,6 +18,7 @@ final class AccountsTests: CollectionTest { /// We can have this test implemented when swift-testing is stable to be used, /// and we will use "exit tests" to test it: /// https://forums.swift.org/t/exit-tests-death-tests-and-you/71186 + @available(*, deprecated) func omit_crash_if_duplicates() { // this test is relevant for Personas, AuthorizedDapps, ProfileNetworks etc etc... they all use the same rust type, which does not allow duplicates var profile = Profile.sample let a = Account.sample @@ -27,12 +28,14 @@ final class AccountsTests: CollectionTest { let _ = profile.jsonData() // should crash } + @available(*, deprecated) func test_json_decoding_of_profile_fails_if_accounts_contains_duplicates() throws { var json = JSON(Profile.sample) json["profileNetworks.accounts"] = [Account.sample, Account.sample] XCTAssertThrowsError(try Profile(jsonData: json.rawData())) } + @available(*, deprecated) func test_json_decoding_of_profile_fails_if_accounts_contains_duplicated_ids() throws { var json = JSON(Profile.sample) let a = Account.sample diff --git a/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift b/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift index ad95d5c41..1b2914fc8 100644 --- a/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift @@ -18,24 +18,28 @@ final class FactorSourcesTests: CollectionTest { /// We can have this test implemented when swift-testing is stable to be used, /// and we will use "exit tests" to test it: /// https://forums.swift.org/t/exit-tests-death-tests-and-you/71186 + @available(*, deprecated) func omit_crash_if_empty() { var profile = Profile.sample profile.factorSources = [] // empty FactorSources is not allowed let _ = profile.jsonData() // should crash } + @available(*, deprecated) func test_json_decoding_of_profile_fails_if_factorSources_is_empty() throws { var json = JSON(Profile.sample) json["factorSources"] = [] XCTAssertThrowsError(try Profile(jsonData: json.rawData())) } + @available(*, deprecated) func test_json_decoding_of_profile_fails_if_factorSources_contains_duplicates() throws { var json = JSON(Profile.sample) json["factorSources"] = [FactorSource.sample, FactorSource.sample] XCTAssertThrowsError(try Profile(jsonData: json.rawData())) } + @available(*, deprecated) func test_json_decoding_of_profile_fails_if_factorSources_contains_duplicated_ids() throws { var json = JSON(Profile.sample) let a = FactorSource.sample diff --git a/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift b/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift index 9cd6e7447..7993c8e35 100644 --- a/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift +++ b/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift @@ -93,6 +93,7 @@ final class DeviceFactorSourceTests: SpecificFactorSourceTest { XCTAssertNoDifference(SUT.sample.id, SUT.sample.header.id) } + @available(*, deprecated) func test_encryption_roundtrip() throws { let password = "ultra secret" let sut = SUT.sample @@ -102,6 +103,7 @@ final class ProfileTests: Test { XCTAssertTrue(jsonString.contains("version")) } + @available(*, deprecated) func test_json_roundtrip() throws { func doTest(_ sut: SUT, _ json: String) throws { let encoded = sut.toJSONString(prettyPrinted: false) @@ -146,8 +148,9 @@ final class ProfileTests: Test { } } + @available(*, deprecated) func test_check_if_profile_json_contains_legacy_p2p_links_when_p2p_links_are_present() throws { - let json = try openFile(subPath: "vector", "only_plaintext_profile_snapshot_version_100", extension: "json") + let json = try jsonData(file: "only_plaintext_profile_snapshot_version_100") XCTAssert( SUT.checkIfProfileJsonContainsLegacyP2PLinks(contents: json) ) @@ -159,15 +162,16 @@ final class ProfileTests: Test { ) } + @available(*, deprecated) func test_check_if_encrypted_profile_json_contains_legacy_p2p_links_when_p2p_links_are_present() throws { - let json = try openFile(subPath: "vector", "profile_encrypted_by_password_of_babylon", extension: "json") + let json = try jsonData(file: "profile_encrypted_by_password_of_babylon") XCTAssert( SUT.checkIfEncryptedProfileJsonContainsLegacyP2PLinks(contents: json, password: "babylon") ) } func test_check_if_encrypted_profile_json_string_contains_legacy_p2p_links_when_p2p_links_are_present() throws { - let json = try openFile(subPath: "vector", "profile_encrypted_by_password_of_babylon", extension: "json") + let json = try jsonData(file: "profile_encrypted_by_password_of_babylon") let jsonString = try XCTUnwrap(String(data: json, encoding: .utf8)) XCTAssert( SUT.checkIfEncryptedProfileJsonStringContainsLegacyP2PLinks(jsonString: jsonString, password: "babylon") diff --git a/apple/Tests/TestCases/RadixConnect/WalletInteraction/WalletToDappInteractionResponseTests.swift b/apple/Tests/TestCases/RadixConnect/WalletInteraction/WalletToDappInteractionResponseTests.swift index 27a1b8d17..42cb97b15 100644 --- a/apple/Tests/TestCases/RadixConnect/WalletInteraction/WalletToDappInteractionResponseTests.swift +++ b/apple/Tests/TestCases/RadixConnect/WalletInteraction/WalletToDappInteractionResponseTests.swift @@ -6,10 +6,9 @@ import XCTest final class WalletToDappInteractionResponseTests: Test { func test_codable() throws { - let json = try openFile( - subPath: "vector", - "wallet_interactions_wallet_to_dapp", - extension: "json" + let json = try jsonData( + file: "wallet_interactions_wallet_to_dapp", + in: "models/interaction" ) let sut = try JSONDecoder().decode([SUT].self, from: json) let encoded = try JSONEncoder().encode(sut) diff --git a/apple/Tests/Utils/Extensions/UUID+Literals.swift b/apple/Tests/Utils/Extensions/UUID+Literals.swift index ee674bfd5..d5dc4734b 100644 --- a/apple/Tests/Utils/Extensions/UUID+Literals.swift +++ b/apple/Tests/Utils/Extensions/UUID+Literals.swift @@ -1,14 +1,16 @@ import Foundation // MARK: - UUID + ExpressibleByStringLiteral -extension UUID: ExpressibleByStringLiteral { +extension UUID: @retroactive ExpressibleByExtendedGraphemeClusterLiteral {} +extension UUID: @retroactive ExpressibleByUnicodeScalarLiteral {} +extension UUID: @retroactive ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.init(uuidString: value)! } } // MARK: - UUID + ExpressibleByIntegerLiteral -extension UUID: ExpressibleByIntegerLiteral { +extension UUID: @retroactive ExpressibleByIntegerLiteral { public init(integerLiteral value: UInt8) { self.init(uuidString: "00000000-0000-0000-0000-0000000000" + String(format: "%02d", value))! } diff --git a/apple/Tests/Utils/Test.swift b/apple/Tests/Utils/Test.swift index d9390b2ab..9abf798eb 100644 --- a/apple/Tests/Utils/Test.swift +++ b/apple/Tests/Utils/Test.swift @@ -40,9 +40,10 @@ class TestCase: XCTestCase { func jsonFixture( as: T.Type = T.self, file fileName: String, + in subPath: String? = nil, decode: (Data) throws -> T = { try JSONDecoder().decode(T.self, from: $0) } ) throws -> (model: T, json: Data) { - let json = try openFile(subPath: "vector", fileName, extension: "json") + let json = try jsonData(file: fileName, in: subPath) let model: T = try decode(json) return (model, json) } @@ -50,23 +51,32 @@ class TestCase: XCTestCase { func jsonFixture( as: T.Type = T.self, file fileName: String, + in subPath: String? = nil, decode: (Data) throws -> T ) throws -> (model: T, json: Data) { - let json = try openFile(subPath: "vector", fileName, extension: "json") + let json = try jsonData(file: fileName, in: subPath) let model: T = try decode(json) return (model, json) } + func jsonData( + file fileName: String, + in subPath: String? = nil + ) throws -> Data { + try openFile( + subPath: subPath ?? "models/profile", + fileName, + extension: "json" + ) + } + func jsonString( as: T.Type = T.self, file fileName: String, + in subPath: String? = nil, decode: (String) throws -> T ) throws -> (model: T, jsonString: String) { - let jsonData = try openFile( - subPath: "vector", - fileName, - extension: "json" - ) + let jsonData = try jsonData(file: fileName, in: subPath) let jsonString = try XCTUnwrap(String(data: jsonData, encoding: .utf8)) let model: T = try decode(jsonString) return (model, jsonString) diff --git a/crates/app/home-cards/Cargo.toml b/crates/app/home-cards/Cargo.toml index 59518c3af..14f75e7ac 100644 --- a/crates/app/home-cards/Cargo.toml +++ b/crates/app/home-cards/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "home-cards" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/app/key-derivation-traits/Cargo.toml b/crates/app/key-derivation-traits/Cargo.toml index 6b329e0c0..7a8e915c5 100644 --- a/crates/app/key-derivation-traits/Cargo.toml +++ b/crates/app/key-derivation-traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "key-derivation-traits" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/app/radix-connect-models/Cargo.toml b/crates/app/radix-connect-models/Cargo.toml index e07d05d96..b9acdcf43 100644 --- a/crates/app/radix-connect-models/Cargo.toml +++ b/crates/app/radix-connect-models/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "radix-connect-models" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/app/radix-connect/Cargo.toml b/crates/app/radix-connect/Cargo.toml index 0a5c77cf6..ae0761d1f 100644 --- a/crates/app/radix-connect/Cargo.toml +++ b/crates/app/radix-connect/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "radix-connect" -version = "1.1.122" +version = "1.1.123" edition = "2021" @@ -25,6 +25,7 @@ entity-foundation = { workspace = true } short-string = { workspace = true } has-sample-values = { workspace = true } radix-connect-models = { workspace = true } +profile-security-structures = { workspace = true } # === RADIX DEPENDENCIES === # None diff --git a/crates/app/radix-connect/src/lib.rs b/crates/app/radix-connect/src/lib.rs index b790456c2..d87d53902 100644 --- a/crates/app/radix-connect/src/lib.rs +++ b/crates/app/radix-connect/src/lib.rs @@ -29,8 +29,9 @@ pub mod prelude { pub(crate) use identified_vec_of::prelude::*; pub(crate) use prelude::prelude::*; pub(crate) use profile_persona_data::prelude::*; + pub(crate) use profile_security_structures::prelude::*; pub(crate) use radix_connect_models::prelude::*; - pub(crate) use short_string::prelude::*; + pub(crate) use transaction_models::prelude::*; // EXTERNAL DEPENDENCIES @@ -49,7 +50,7 @@ pub mod prelude { mod testing { pub(crate) use drivers::prelude::MockNetworkingDriver; pub(crate) use serde_json::json; - pub(crate) use std::collections::{BTreeSet, HashSet}; + pub(crate) use std::collections::BTreeSet; } } diff --git a/crates/app/radix-connect/src/mobile/deep_link_parsing/parser.rs b/crates/app/radix-connect/src/mobile/deep_link_parsing/parser.rs index a36855b3d..4ad1c2b36 100644 --- a/crates/app/radix-connect/src/mobile/deep_link_parsing/parser.rs +++ b/crates/app/radix-connect/src/mobile/deep_link_parsing/parser.rs @@ -171,7 +171,7 @@ impl SampleRequestParams { } pub fn new_from_text_vector() -> Self { - fixture::(prelude::fixture_vector!( + fixture::(prelude::fixture_interaction!( "deep_link_request_params" )) .unwrap() diff --git a/crates/app/radix-connect/src/wallet_interaction/dapp_wallet_interaction/dapp_to_wallet/interaction_items/batch_of_transactions/batch_of_transactions.rs b/crates/app/radix-connect/src/wallet_interaction/dapp_wallet_interaction/dapp_to_wallet/interaction_items/batch_of_transactions/batch_of_transactions.rs index 7b69b36c8..a35045129 100644 --- a/crates/app/radix-connect/src/wallet_interaction/dapp_wallet_interaction/dapp_to_wallet/interaction_items/batch_of_transactions/batch_of_transactions.rs +++ b/crates/app/radix-connect/src/wallet_interaction/dapp_wallet_interaction/dapp_to_wallet/interaction_items/batch_of_transactions/batch_of_transactions.rs @@ -1,3 +1,5 @@ +use prelude::fixture_rtm; + use crate::prelude::*; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] @@ -17,14 +19,33 @@ impl DappToWalletInteractionBatchOfTransactions { impl HasSampleValues for DappToWalletInteractionBatchOfTransactions { fn sample() -> Self { - Self::new([ - UnvalidatedTransactionManifest::sample(), - UnvalidatedTransactionManifest::sample_other(), - ]) + let init_p_conf_r = TransactionManifest::new( + fixture_rtm!("update_shield_of_persona_init_with_R_confirm_with_P"), + NetworkID::Mainnet, + Blobs::default(), + ) + .unwrap(); + let unsecurified = TransactionManifest::new( + fixture_rtm!("create_access_controller_for_account"), + NetworkID::Mainnet, + Blobs::default(), + ) + .unwrap(); + Self::new( + [init_p_conf_r, unsecurified] + .map(UnvalidatedTransactionManifest::from), + ) } fn sample_other() -> Self { - Self::new([UnvalidatedTransactionManifest::sample_other()]) + let init_p_conf_c = TransactionManifest::new( + fixture_rtm!("update_shield_of_persona_init_with_R_confirm_with_P"), + NetworkID::Mainnet, + Blobs::default(), + ) + .unwrap(); + + Self::new([init_p_conf_c].map(UnvalidatedTransactionManifest::from)) } } diff --git a/crates/app/security-center/Cargo.toml b/crates/app/security-center/Cargo.toml index f9afcb614..6a7876f8f 100644 --- a/crates/app/security-center/Cargo.toml +++ b/crates/app/security-center/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "security-center" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/app/signing-traits/Cargo.toml b/crates/app/signing-traits/Cargo.toml index 8c917adfb..dca48b74f 100644 --- a/crates/app/signing-traits/Cargo.toml +++ b/crates/app/signing-traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "signing-traits" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/app/signing-traits/src/lib.rs b/crates/app/signing-traits/src/lib.rs index d778cc859..a5aa59af9 100644 --- a/crates/app/signing-traits/src/lib.rs +++ b/crates/app/signing-traits/src/lib.rs @@ -38,14 +38,6 @@ pub mod prelude { pub(crate) use indexmap::{IndexMap, IndexSet}; pub(crate) use std::fmt::Debug; - - #[cfg(test)] - pub(crate) use testing::*; - - #[cfg(test)] - mod testing { - pub(crate) use std::collections::HashSet; - } } pub use prelude::*; diff --git a/crates/common/build-info/Cargo.toml b/crates/common/build-info/Cargo.toml index b3a2e82a0..abd960c36 100644 --- a/crates/common/build-info/Cargo.toml +++ b/crates/common/build-info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "build-info" -version = "1.1.122" +version = "1.1.123" edition = "2021" build = "build.rs" diff --git a/crates/common/bytes/Cargo.toml b/crates/common/bytes/Cargo.toml index 10c593140..d939f537c 100644 --- a/crates/common/bytes/Cargo.toml +++ b/crates/common/bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bytes" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/entity-foundation/Cargo.toml b/crates/common/entity-foundation/Cargo.toml index 320ac6313..ac6145815 100644 --- a/crates/common/entity-foundation/Cargo.toml +++ b/crates/common/entity-foundation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "entity-foundation" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/host-info/Cargo.toml b/crates/common/host-info/Cargo.toml index 3fdefcbfd..eddfd2473 100644 --- a/crates/common/host-info/Cargo.toml +++ b/crates/common/host-info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "host-info" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/identified-vec-of/Cargo.toml b/crates/common/identified-vec-of/Cargo.toml index 523c65daf..c06dde9bc 100644 --- a/crates/common/identified-vec-of/Cargo.toml +++ b/crates/common/identified-vec-of/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "identified-vec-of" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/metadata/Cargo.toml b/crates/common/metadata/Cargo.toml index 657ff501c..3b24f6463 100644 --- a/crates/common/metadata/Cargo.toml +++ b/crates/common/metadata/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "metadata" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/network/Cargo.toml b/crates/common/network/Cargo.toml index d45faf872..5d511fe71 100644 --- a/crates/common/network/Cargo.toml +++ b/crates/common/network/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "network" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/numeric/Cargo.toml b/crates/common/numeric/Cargo.toml index ddba92c78..b16e225ea 100644 --- a/crates/common/numeric/Cargo.toml +++ b/crates/common/numeric/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "numeric" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/common/numeric/src/decimal/decimal192.rs b/crates/common/numeric/src/decimal/decimal192.rs index 5490e5c1f..2131b0088 100644 --- a/crates/common/numeric/src/decimal/decimal192.rs +++ b/crates/common/numeric/src/decimal/decimal192.rs @@ -59,7 +59,7 @@ impl Decimal { self.0 } - fn from_native(decimal: ScryptoDecimal192) -> Self { + pub const fn from_native(decimal: ScryptoDecimal192) -> Self { Self(decimal) } diff --git a/crates/common/short-string/Cargo.toml b/crates/common/short-string/Cargo.toml index 78753bf4d..79a88098e 100644 --- a/crates/common/short-string/Cargo.toml +++ b/crates/common/short-string/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "short-string" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/assert-json/Cargo.toml b/crates/core/assert-json/Cargo.toml index 7019c6dab..5a95ce8f1 100644 --- a/crates/core/assert-json/Cargo.toml +++ b/crates/core/assert-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "assert-json" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/collections/Cargo.toml b/crates/core/collections/Cargo.toml index 677337f3f..0c4fcb4c1 100644 --- a/crates/core/collections/Cargo.toml +++ b/crates/core/collections/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "core-collections" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/error/Cargo.toml b/crates/core/error/Cargo.toml index 7970518d0..dc29f5b1a 100644 --- a/crates/core/error/Cargo.toml +++ b/crates/core/error/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/has-sample-values/Cargo.toml b/crates/core/has-sample-values/Cargo.toml index b41303dff..795e59c87 100644 --- a/crates/core/has-sample-values/Cargo.toml +++ b/crates/core/has-sample-values/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "has-sample-values" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/misc/Cargo.toml b/crates/core/misc/Cargo.toml index 509c05bca..3765026d0 100644 --- a/crates/core/misc/Cargo.toml +++ b/crates/core/misc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "core-misc" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/prelude/Cargo.toml b/crates/core/prelude/Cargo.toml index f3437d964..5ad0b247d 100644 --- a/crates/core/prelude/Cargo.toml +++ b/crates/core/prelude/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "prelude" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/prelude/src/lib.rs b/crates/core/prelude/src/lib.rs index 9e572d391..5f49dab9a 100644 --- a/crates/core/prelude/src/lib.rs +++ b/crates/core/prelude/src/lib.rs @@ -47,7 +47,38 @@ macro_rules! fixture_gw_model { }; } +#[macro_export] +macro_rules! fixture_profiles { + ($file: expr) => { + $crate::fixture_in!( + env!("FIXTURES_MODELS_PROFILES"), + concat!($file, ".json") + ) + }; +} + +#[macro_export] +macro_rules! fixture_profile_model { + ($file: expr) => { + $crate::fixture_in!( + env!("FIXTURES_MODELS_PROFILE"), + concat!($file, ".json") + ) + }; +} + +#[macro_export] +macro_rules! fixture_interaction { + ($file: expr) => { + $crate::fixture_in!( + env!("FIXTURES_MODELS_INTERACTION"), + concat!($file, ".json") + ) + }; +} + pub mod prelude { + pub use std::collections::HashSet; pub use std::str::FromStr; pub use std::sync::{Arc, RwLock}; } diff --git a/crates/core/time-utils/Cargo.toml b/crates/core/time-utils/Cargo.toml index c0e4658c0..133741a04 100644 --- a/crates/core/time-utils/Cargo.toml +++ b/crates/core/time-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "time-utils" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/core/utils/Cargo.toml b/crates/core/utils/Cargo.toml index a071a11c3..7793188f9 100644 --- a/crates/core/utils/Cargo.toml +++ b/crates/core/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "core-utils" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/addresses/Cargo.toml b/crates/crypto/addresses/Cargo.toml index 194655bd0..541a3f906 100644 --- a/crates/crypto/addresses/Cargo.toml +++ b/crates/crypto/addresses/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "addresses" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/cap26-models/Cargo.toml b/crates/crypto/cap26-models/Cargo.toml index 22dcb27bd..933111226 100644 --- a/crates/crypto/cap26-models/Cargo.toml +++ b/crates/crypto/cap26-models/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cap26-models" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/ecc/Cargo.toml b/crates/crypto/ecc/Cargo.toml index f2643de4c..08dd43cc9 100644 --- a/crates/crypto/ecc/Cargo.toml +++ b/crates/crypto/ecc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ecc" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/encryption/Cargo.toml b/crates/crypto/encryption/Cargo.toml index 362eb4f79..d278a2ed5 100644 --- a/crates/crypto/encryption/Cargo.toml +++ b/crates/crypto/encryption/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "encryption" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/hash/Cargo.toml b/crates/crypto/hash/Cargo.toml index 5ba311328..734d6775e 100644 --- a/crates/crypto/hash/Cargo.toml +++ b/crates/crypto/hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hash" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/crypto/hd/Cargo.toml b/crates/crypto/hd/Cargo.toml index 86e48fc84..f8afd2ec3 100644 --- a/crates/crypto/hd/Cargo.toml +++ b/crates/crypto/hd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hierarchical-deterministic" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/factors/factors/Cargo.toml b/crates/factors/factors/Cargo.toml index ebdf6df63..20c186115 100644 --- a/crates/factors/factors/Cargo.toml +++ b/crates/factors/factors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factors" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/factors/factors/src/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs b/crates/factors/factors/src/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs index 18e9069c6..4e74b7580 100644 --- a/crates/factors/factors/src/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs +++ b/crates/factors/factors/src/mfa_factor_sources/security_questions_factor_source/security_questions_factor_source.rs @@ -1,5 +1,5 @@ use encryption::EncryptionScheme; -use prelude::fixture_vector; +use prelude::fixture_profile_model; use crate::prelude::*; @@ -195,7 +195,8 @@ impl SecurityQuestions_NOT_PRODUCTION_READY_FactorSource { impl HasSampleValues for SecurityQuestions_NOT_PRODUCTION_READY_FactorSource { fn sample() -> Self { - let json = fixture_vector!("security_questions_factor_source_sample"); + let json = + fixture_profile_model!("security_questions_factor_source_sample"); let sut = serde_json::from_str::(json).unwrap(); let decrypted = sut.decrypt( @@ -207,8 +208,9 @@ impl HasSampleValues for SecurityQuestions_NOT_PRODUCTION_READY_FactorSource { } fn sample_other() -> Self { - let json = - fixture_vector!("security_questions_factor_source_sample_other"); + let json = fixture_profile_model!( + "security_questions_factor_source_sample_other" + ); let sut = serde_json::from_str::(json).unwrap(); let decrypted = sut .decrypt( diff --git a/crates/factors/instances-provider/Cargo.toml b/crates/factors/instances-provider/Cargo.toml index e35baf445..d232bb927 100644 --- a/crates/factors/instances-provider/Cargo.toml +++ b/crates/factors/instances-provider/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factor-instances-provider" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/factors/instances-provider/src/next_index_assigner/next_derivation_entity_index_profile_analyzing_assigner.rs b/crates/factors/instances-provider/src/next_index_assigner/next_derivation_entity_index_profile_analyzing_assigner.rs index 2335a1197..c7a6030e5 100644 --- a/crates/factors/instances-provider/src/next_index_assigner/next_derivation_entity_index_profile_analyzing_assigner.rs +++ b/crates/factors/instances-provider/src/next_index_assigner/next_derivation_entity_index_profile_analyzing_assigner.rs @@ -483,7 +483,7 @@ mod tests { ConfirmationRoleWithFactorInstances::override_only( [fi.clone()], ), - 10, + TimePeriod::with_days(10), ) }; @@ -539,7 +539,7 @@ mod tests { ConfirmationRoleWithFactorInstances::override_only( [fi.clone()], ), - 10, + TimePeriod::with_days(10), ) }; @@ -675,7 +675,7 @@ mod tests { ConfirmationRoleWithFactorInstances::override_only( factors.clone(), ), - 123, + TimePeriod::with_days(123), ) }; diff --git a/crates/factors/keys-collector/Cargo.toml b/crates/factors/keys-collector/Cargo.toml index cdbbde1c0..5d034119d 100644 --- a/crates/factors/keys-collector/Cargo.toml +++ b/crates/factors/keys-collector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keys-collector" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/factors/keys-collector/src/lib.rs b/crates/factors/keys-collector/src/lib.rs index 7bc15254c..91042b42b 100644 --- a/crates/factors/keys-collector/src/lib.rs +++ b/crates/factors/keys-collector/src/lib.rs @@ -21,7 +21,7 @@ pub mod prelude { pub(crate) use indexmap::{IndexMap, IndexSet}; pub(crate) use log::*; - pub(crate) use std::collections::{HashMap, HashSet}; + pub(crate) use std::collections::HashMap; #[cfg(test)] pub(crate) use testing::*; diff --git a/crates/factors/next-derivation-index-ephemeral/Cargo.toml b/crates/factors/next-derivation-index-ephemeral/Cargo.toml index b79188df8..cfa4f79ec 100644 --- a/crates/factors/next-derivation-index-ephemeral/Cargo.toml +++ b/crates/factors/next-derivation-index-ephemeral/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "next-derivation-index-ephemeral" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/factors/signatures-collector/Cargo.toml b/crates/factors/signatures-collector/Cargo.toml index b55baba99..a916062d0 100644 --- a/crates/factors/signatures-collector/Cargo.toml +++ b/crates/factors/signatures-collector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "signatures-collector" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/factors/signatures-collector/src/lib.rs b/crates/factors/signatures-collector/src/lib.rs index 6059f35a9..0ff995c6e 100644 --- a/crates/factors/signatures-collector/src/lib.rs +++ b/crates/factors/signatures-collector/src/lib.rs @@ -31,7 +31,7 @@ pub mod prelude { pub(crate) use transaction_models::prelude::*; pub(crate) use log::*; - pub(crate) use std::collections::{HashMap, HashSet}; + pub(crate) use std::collections::HashMap; #[cfg(test)] pub(crate) use testing::*; diff --git a/crates/factors/signatures-collector/src/tests/auth_intent_hash.rs b/crates/factors/signatures-collector/src/tests/auth_intent_hash.rs index 23501bdfc..349d47e16 100644 --- a/crates/factors/signatures-collector/src/tests/auth_intent_hash.rs +++ b/crates/factors/signatures-collector/src/tests/auth_intent_hash.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod tests { - use prelude::fixture_vector; + use prelude::fixture_interaction; use serde::{de, Deserializer}; use crate::prelude::*; @@ -52,7 +52,7 @@ mod tests { #[test] fn test_from_vectors() { - let json = fixture_vector!("rola_challenge_payload_hash_vectors"); + let json = fixture_interaction!("rola_challenge_payload_hash_vectors"); let vector = serde_json::from_str::>(json) .unwrap(); diff --git a/crates/factors/supporting-types/Cargo.toml b/crates/factors/supporting-types/Cargo.toml index f7ce891ba..329da23bd 100644 --- a/crates/factors/supporting-types/Cargo.toml +++ b/crates/factors/supporting-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "factors-supporting-types" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/gateway/client-and-api/Cargo.toml b/crates/gateway/client-and-api/Cargo.toml index f669ce29b..17b64fb48 100644 --- a/crates/gateway/client-and-api/Cargo.toml +++ b/crates/gateway/client-and-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gateway-client-and-api" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/gateway/models/Cargo.toml b/crates/gateway/models/Cargo.toml index 694c35229..d691d8275 100644 --- a/crates/gateway/models/Cargo.toml +++ b/crates/gateway/models/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gateway-models" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/profile/logic/logic_SPLIT_ME/Cargo.toml b/crates/profile/logic/logic_SPLIT_ME/Cargo.toml index 0c8aa450f..64904af2d 100644 --- a/crates/profile/logic/logic_SPLIT_ME/Cargo.toml +++ b/crates/profile/logic/logic_SPLIT_ME/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-logic" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/logic/logic_SPLIT_ME/src/tests/matrix_of_factor_instances_index_agnostic.rs b/crates/profile/logic/logic_SPLIT_ME/src/tests/matrix_of_factor_instances_index_agnostic.rs index 09e61ed59..314534641 100644 --- a/crates/profile/logic/logic_SPLIT_ME/src/tests/matrix_of_factor_instances_index_agnostic.rs +++ b/crates/profile/logic/logic_SPLIT_ME/src/tests/matrix_of_factor_instances_index_agnostic.rs @@ -27,7 +27,7 @@ fn wrong_entity_kind() { [], [], ), - 1, + TimePeriod::with_days(1), ) }; let res = invalid.index_agnostic_path_of_all_tx_signing_factor_instances(); @@ -62,7 +62,7 @@ fn wrong_key_kind() { [], [], ), - 1, + TimePeriod::with_days(1), ) }; let res = invalid.index_agnostic_path_of_all_tx_signing_factor_instances(); diff --git a/crates/profile/models/account-for-display/Cargo.toml b/crates/profile/models/account-for-display/Cargo.toml index a95d1bb75..b3b34bc3e 100644 --- a/crates/profile/models/account-for-display/Cargo.toml +++ b/crates/profile/models/account-for-display/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "account-for-display" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/account-or-persona/Cargo.toml b/crates/profile/models/account-or-persona/Cargo.toml index 4234de7f1..a6dac7d82 100644 --- a/crates/profile/models/account-or-persona/Cargo.toml +++ b/crates/profile/models/account-or-persona/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-account-or-persona" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/account/Cargo.toml b/crates/profile/models/account/Cargo.toml index 299355d40..329947f2f 100644 --- a/crates/profile/models/account/Cargo.toml +++ b/crates/profile/models/account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-account" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/account/src/lib.rs b/crates/profile/models/account/src/lib.rs index 8dea804ea..d7d886e42 100644 --- a/crates/profile/models/account/src/lib.rs +++ b/crates/profile/models/account/src/lib.rs @@ -18,14 +18,6 @@ pub mod prelude { pub(crate) use transaction_models::prelude::*; pub(crate) use serde::{Deserialize, Serialize}; - - #[cfg(test)] - pub(crate) use testing::*; - - #[cfg(test)] - mod testing { - pub(crate) use std::collections::HashSet; - } } pub use prelude::*; diff --git a/crates/profile/models/app-preferences/Cargo.toml b/crates/profile/models/app-preferences/Cargo.toml index 2546a9574..1d9eca101 100644 --- a/crates/profile/models/app-preferences/Cargo.toml +++ b/crates/profile/models/app-preferences/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-app-preferences" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/app-preferences/src/security.rs b/crates/profile/models/app-preferences/src/security.rs index f2c84984c..6f94e1114 100644 --- a/crates/profile/models/app-preferences/src/security.rs +++ b/crates/profile/models/app-preferences/src/security.rs @@ -247,7 +247,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } }, { @@ -304,7 +307,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } } ] diff --git a/crates/profile/models/base-entity/Cargo.toml b/crates/profile/models/base-entity/Cargo.toml index 02676c365..47c33fdbb 100644 --- a/crates/profile/models/base-entity/Cargo.toml +++ b/crates/profile/models/base-entity/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-base-entity" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/base-entity/src/entity_security_state/entity_security_state.rs b/crates/profile/models/base-entity/src/entity_security_state/entity_security_state.rs index 05e10e1af..592e31bfc 100644 --- a/crates/profile/models/base-entity/src/entity_security_state/entity_security_state.rs +++ b/crates/profile/models/base-entity/src/entity_security_state/entity_security_state.rs @@ -382,7 +382,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { @@ -508,7 +511,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { diff --git a/crates/profile/models/base-entity/src/entity_security_state/secured_entity_control/secured_entity_control.rs b/crates/profile/models/base-entity/src/entity_security_state/secured_entity_control/secured_entity_control.rs index 7b1cd4892..07b48b397 100644 --- a/crates/profile/models/base-entity/src/entity_security_state/secured_entity_control/secured_entity_control.rs +++ b/crates/profile/models/base-entity/src/entity_security_state/secured_entity_control/secured_entity_control.rs @@ -349,7 +349,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { @@ -475,7 +478,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { diff --git a/crates/profile/models/gateway/Cargo.toml b/crates/profile/models/gateway/Cargo.toml index 05b5aaed6..261433daf 100644 --- a/crates/profile/models/gateway/Cargo.toml +++ b/crates/profile/models/gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-gateway" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/persona-data/Cargo.toml b/crates/profile/models/persona-data/Cargo.toml index 733a81327..75ce4dba5 100644 --- a/crates/profile/models/persona-data/Cargo.toml +++ b/crates/profile/models/persona-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-persona-data" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/persona/Cargo.toml b/crates/profile/models/persona/Cargo.toml index 5b27913c7..d03822aa0 100644 --- a/crates/profile/models/persona/Cargo.toml +++ b/crates/profile/models/persona/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-persona" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/profile_SPLIT_ME/Cargo.toml b/crates/profile/models/profile_SPLIT_ME/Cargo.toml index 5974aaa35..67d457720 100644 --- a/crates/profile/models/profile_SPLIT_ME/Cargo.toml +++ b/crates/profile/models/profile_SPLIT_ME/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/profile/models/profile_SPLIT_ME/src/encrypted_profile/encrypted_profile_snapshot.rs b/crates/profile/models/profile_SPLIT_ME/src/encrypted_profile/encrypted_profile_snapshot.rs index b66fb2665..e37442d7f 100644 --- a/crates/profile/models/profile_SPLIT_ME/src/encrypted_profile/encrypted_profile_snapshot.rs +++ b/crates/profile/models/profile_SPLIT_ME/src/encrypted_profile/encrypted_profile_snapshot.rs @@ -2,7 +2,7 @@ use encryption::{ EncryptionKey, EncryptionScheme, PasswordBasedKeyDerivationScheme, VersionedEncryption, VersionedPasswordBasedKeyDerivation, }; -use prelude::fixture_vector; +use prelude::fixture_profiles; use crate::prelude::*; @@ -92,13 +92,13 @@ impl HasSampleValues for EncryptedProfileSnapshot { /// Password is: `"babylon"` - encryption of SAME profile as `Self::sample_other()` fn sample() -> Self { let json_str = - fixture_vector!("profile_encrypted_by_password_of_babylon"); + fixture_profiles!("profile_encrypted_by_password_of_babylon"); serde_json::from_str::(json_str).unwrap() } /// Password is: `""` (empty) - encryption of SAME profile as `Self::sample()` fn sample_other() -> Self { - let json_str = fixture_vector!("profile_encrypted_by_password_empty"); + let json_str = fixture_profiles!("profile_encrypted_by_password_empty"); serde_json::from_str::(json_str).unwrap() } } diff --git a/crates/profile/models/profile_SPLIT_ME/src/lib.rs b/crates/profile/models/profile_SPLIT_ME/src/lib.rs index b1ba60f6f..cb8d32545 100644 --- a/crates/profile/models/profile_SPLIT_ME/src/lib.rs +++ b/crates/profile/models/profile_SPLIT_ME/src/lib.rs @@ -38,7 +38,4 @@ pub mod prelude { #[cfg(test)] pub(crate) use serde_json::json; - - #[cfg(test)] - pub(crate) use std::collections::HashSet; } diff --git a/crates/profile/models/profile_SPLIT_ME/src/v100/profile.rs b/crates/profile/models/profile_SPLIT_ME/src/v100/profile.rs index b7b2bc919..7eba24736 100644 --- a/crates/profile/models/profile_SPLIT_ME/src/v100/profile.rs +++ b/crates/profile/models/profile_SPLIT_ME/src/v100/profile.rs @@ -399,7 +399,7 @@ impl HasSampleValues for Profile { #[cfg(test)] mod tests { - use prelude::fixture_vector; + use prelude::fixture_profiles; use super::*; @@ -638,7 +638,7 @@ mod tests { fn check_if_profile_json_contains_legacy_p2p_links_in_profile_snapshot_version_100( ) { let json = - fixture_vector!("only_plaintext_profile_snapshot_version_100"); + fixture_profiles!("only_plaintext_profile_snapshot_version_100"); assert!(SUT::check_if_profile_json_contains_legacy_p2p_links(json)); } diff --git a/crates/profile/models/security-structures/Cargo.toml b/crates/profile/models/security-structures/Cargo.toml index 4741e5a75..1d099f9b8 100644 --- a/crates/profile/models/security-structures/Cargo.toml +++ b/crates/profile/models/security-structures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-security-structures" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/security-structures/src/lib.rs b/crates/profile/models/security-structures/src/lib.rs index e18644041..e484892b5 100644 --- a/crates/profile/models/security-structures/src/lib.rs +++ b/crates/profile/models/security-structures/src/lib.rs @@ -43,6 +43,4 @@ pub mod prelude { pub(crate) use serde::{Deserialize, Serialize}; #[cfg(test)] pub(crate) use serde_json::json; - - pub(crate) use std::collections::HashSet; } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/abstract_matrix_builder_or_built.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/abstract_matrix_builder_or_built.rs index 70bb418d4..a5b5ec229 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/abstract_matrix_builder_or_built.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/abstract_matrix_builder_or_built.rs @@ -39,13 +39,14 @@ pub struct AbstractMatrixBuilderOrBuilt< pub(crate) confirmation_role: AbstractRoleBuilderOrBuilt<{ ROLE_CONFIRMATION }, MODE_OF_ROLE, FACTOR>, - pub number_of_days_until_auto_confirm: u16, + pub time_until_delayed_confirmation_is_callable: TimePeriod, } impl AbstractMatrixBuilderOrBuilt { - pub const DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM: u16 = 14; + pub const DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE: TimePeriod = + TimePeriod::with_days(14); /// # Safety /// Rust memory safe, but marked "unsafe" since it might allow for unsafe @@ -109,13 +110,13 @@ impl MODE_OF_ROLE, FACTOR, >, - number_of_days_until_auto_confirm: u16, + time_until_delayed_confirmation_is_callable: TimePeriod, ) -> Self { Self { primary_role, recovery_role, confirmation_role, - number_of_days_until_auto_confirm, + time_until_delayed_confirmation_is_callable, } } } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/error.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/error.rs index 9b39b7a16..63e17e5b8 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/error.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/error.rs @@ -17,8 +17,8 @@ pub enum MatrixRolesInCombinationBasicViolation { #[error("The factor source was not found in any role")] FactorSourceNotFoundInAnyRole, - #[error("The number of days until auto confirm must be greater than zero")] - NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero, + #[error("The number of days until timed confirm is callable must be greater than zero")] + NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)] diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs index 1e942feb9..60544c0f8 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs @@ -12,7 +12,7 @@ pub type MatrixBuilderBuildResult = /// * RecoveryRoleBuilder /// * ConfirmationRoleBuilder /// -/// And `number_of_days_until_auto_confirm`. +/// And `time_until_delayed_confirmation_is_callable`. pub type MatrixBuilder = AbstractMatrixBuilderOrBuilt< IS_MATRIX_BUILDER, IS_ROLE_BUILDER, @@ -28,8 +28,8 @@ impl MatrixBuilder { primary_role: PrimaryRoleBuilder::new(), recovery_role: RecoveryRoleBuilder::new(), confirmation_role: ConfirmationRoleBuilder::new(), - number_of_days_until_auto_confirm: - Self::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM, + time_until_delayed_confirmation_is_callable: + Self::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE, } } @@ -37,7 +37,7 @@ impl MatrixBuilder { /// /// If valid it returns a "built" `MatrixOfFactorSourceIds`. pub fn build(&self) -> MatrixBuilderBuildResult { - self.validate_number_of_days_until_auto_confirm()?; + self.validate_time_until_delayed_confirmation_is_callable()?; let primary = self .primary_role @@ -61,7 +61,7 @@ impl MatrixBuilder { primary, recovery, confirmation, - self.number_of_days_until_auto_confirm, + self.time_until_delayed_confirmation_is_callable, ) }; Ok(built) @@ -379,17 +379,20 @@ impl MatrixBuilder { self.primary_role.get_threshold() } - pub fn set_number_of_days_until_auto_confirm( + pub fn set_time_until_delayed_confirmation_is_callable( &mut self, number_of_days: u16, ) -> MatrixBuilderMutateResult { - self.number_of_days_until_auto_confirm = number_of_days; + self.time_until_delayed_confirmation_is_callable = + TimePeriod::with_days(number_of_days); - self.validate_number_of_days_until_auto_confirm() + self.validate_time_until_delayed_confirmation_is_callable() } - pub fn get_number_of_days_until_auto_confirm(&self) -> u16 { - self.number_of_days_until_auto_confirm + pub fn get_time_until_delayed_confirmation_is_callable( + &self, + ) -> TimePeriod { + self.time_until_delayed_confirmation_is_callable } fn remove_factor_from_role( @@ -533,13 +536,13 @@ impl MatrixBuilder { } } - fn validate_number_of_days_until_auto_confirm( + fn validate_time_until_delayed_confirmation_is_callable( &self, ) -> MatrixBuilderMutateResult { - if self.number_of_days_until_auto_confirm == 0 { + if self.time_until_delayed_confirmation_is_callable.is_zero() { return Err(MatrixBuilderValidation::CombinationViolation( MatrixRolesInCombinationViolation::Basic( - MatrixRolesInCombinationBasicViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero, + MatrixRolesInCombinationBasicViolation::NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero, ), )); } @@ -603,14 +606,14 @@ impl MatrixBuilder { /// 1. If only one factor is used for `Primary`, that factor may not be used for either `Recovery` or `Confirmation` /// 2. No factor may be used (override) in both `Recovery` and `Confirmation` /// 3. No factor may be used in both the `Primary` threshold and `Primary` override - /// 4. Number of days until auto confirm is greater than zero + /// 4. Number of days until timed confirm is callable is greater than zero fn validate_combination(&self) -> MatrixBuilderMutateResult { self.validate_if_primary_has_single_it_must_not_be_used_by_any_other_role()?; self.validate_primary_cannot_have_multiple_devices()?; self.validate_no_factor_may_be_used_in_both_primary_threshold_and_override()?; self.validate_no_factor_may_be_used_in_both_recovery_and_confirmation( )?; - self.validate_number_of_days_until_auto_confirm()?; + self.validate_time_until_delayed_confirmation_is_callable()?; Ok(()) } } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder_unit_tests.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder_unit_tests.rs index c3515b99a..f6f51190e 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder_unit_tests.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder_unit_tests.rs @@ -86,11 +86,11 @@ fn set_number_of_days_cannot_be_zero() { ) .unwrap(); - sut.number_of_days_until_auto_confirm = 0; // bypass validation + sut.time_until_delayed_confirmation_is_callable = TimePeriod::with_days(0); // bypass validation // Build let validation = MatrixBuilderValidation::CombinationViolation( - MatrixRolesInCombinationViolation::Basic(MatrixRolesInCombinationBasicViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero) + MatrixRolesInCombinationViolation::Basic(MatrixRolesInCombinationBasicViolation::NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero) ); assert_eq!(sut.validate(), Err(validation)); let res = sut.build(); @@ -117,7 +117,8 @@ fn set_number_of_days_42() { ) .unwrap(); - sut.set_number_of_days_until_auto_confirm(42).unwrap(); + sut.set_time_until_delayed_confirmation_is_callable(42) + .unwrap(); // Build assert!(sut.validate().is_ok()); @@ -136,14 +137,17 @@ fn set_number_of_days_42() { ConfirmationRoleWithFactorSourceIds::override_only([ FactorSourceID::sample_password() ],), - 42, + TimePeriod::with_days(42), ) ); } #[test] -fn auto_confirm_default() { - assert_eq!(SUT::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM, 14); +fn timed_confirm_default() { + assert_eq!( + SUT::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE, + TimePeriod::with_days(14) + ); } #[test] @@ -183,7 +187,7 @@ fn set_number_of_days_if_not_set_uses_default() { ConfirmationRoleWithFactorSourceIds::override_only([ FactorSourceID::sample_password() ],), - SUT::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM, + SUT::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE, ) ); } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_template.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_template.rs index 9e2af5daa..70df4ead8 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_template.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_template.rs @@ -82,8 +82,8 @@ impl MatrixTemplate { self, factor_source_ids: impl IntoIterator, ) -> Result { - let number_of_days_until_auto_confirm = - self.number_of_days_until_auto_confirm; + let time_until_delayed_confirmation_is_callable = + self.time_until_delayed_confirmation_is_callable; let mut assigner = FactorSourceIdAssigner::new(factor_source_ids); @@ -98,7 +98,7 @@ impl MatrixTemplate { primary_role, recovery_role, confirmation_role, - number_of_days_until_auto_confirm, + time_until_delayed_confirmation_is_callable, ) }; @@ -113,7 +113,7 @@ impl MatrixTemplate { confirmation_role: ConfirmationRoleTemplate, ) -> Self { unsafe { - Self::unbuilt_with_roles_and_days(primary_role, recovery_role, confirmation_role, MatrixOfFactorSourceIds::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM) + Self::unbuilt_with_roles_and_days(primary_role, recovery_role, confirmation_role, MatrixOfFactorSourceIds::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE) } } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_instances.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_instances.rs index dc07b35b4..eb4d0d35f 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_instances.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_instances.rs @@ -4,9 +4,8 @@ pub type MatrixOfFactorInstances = AbstractMatrixBuilt; impl MatrixOfFactorInstances { pub fn timed_recovery_delay_in_minutes(&self) -> u32 { - let timed_recovery_in_days = - self.number_of_days_until_auto_confirm as u32; - MINUTES_PER_DAY * timed_recovery_in_days + self.time_until_delayed_confirmation_is_callable + .in_minutes() } } @@ -290,7 +289,8 @@ impl MatrixOfFactorInstances { primary_role, recovery_role, confirmation_role, - matrix_of_factor_sources.number_of_days_until_auto_confirm, + matrix_of_factor_sources + .time_until_delayed_confirmation_is_callable, ) }; @@ -337,10 +337,7 @@ mod tests { #[test] fn timed_recovery_delay_in_minutes() { let sut = SUT::sample(); - assert_eq!( - sut.timed_recovery_delay_in_minutes(), - SUT::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM as u32 * 24 * 60 - ); + assert_eq!(sut.timed_recovery_delay_in_minutes(), 14_u32 * 24 * 60); } #[test] @@ -382,7 +379,7 @@ mod tests { [], [], ), - 1, + TimePeriod::with_days(1), ) }; let res = @@ -557,7 +554,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } "#, ); diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_source_ids.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_source_ids.rs index aed8c4abb..c5383e032 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_source_ids.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_source_ids.rs @@ -13,7 +13,7 @@ impl MatrixOfFactorSourceIds { primary, recovery, confirmation, - Self::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM, + Self::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE, ) } } @@ -25,14 +25,14 @@ impl MatrixOfFactorSourceIds { primary: PrimaryRoleWithFactorSourceIds, recovery: RecoveryRoleWithFactorSourceIds, confirmation: ConfirmationRoleWithFactorSourceIds, - number_of_days_until_auto_confirm: u16, + time_until_delayed_confirmation_is_callable: TimePeriod, ) -> Self { unsafe { Self::unbuilt_with_roles_and_days( primary, recovery, confirmation, - number_of_days_until_auto_confirm, + time_until_delayed_confirmation_is_callable, ) } } @@ -46,7 +46,7 @@ impl MatrixOfFactorSourceIds { primary, recovery, confirmation, - Self::DEFAULT_NUMBER_OF_DAYS_UNTIL_AUTO_CONFIRM, + Self::DEFAULT_TIME_UNTIL_DELAYED_CONFIRMATION_IS_CALLABLE, ) } } @@ -321,7 +321,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } "#, ); @@ -373,7 +376,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } "#, ); diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_sources.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_sources.rs index eb9cbf67d..d3d8a6801 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_sources.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/matrix_of_factor_sources.rs @@ -30,7 +30,7 @@ impl MatrixOfFactorSources { primary_role, recovery_role, confirmation_role, - matrix.number_of_days_until_auto_confirm, + matrix.time_until_delayed_confirmation_is_callable, ) }; diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs index 42b5bc54c..aac3b182a 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs @@ -275,11 +275,9 @@ impl SecurityShieldBuilder { }) } - pub fn get_time_period_until_auto_confirm(&self) -> TimePeriod { + pub fn get_time_until_timed_confirmation_is_callable(&self) -> TimePeriod { self.get(|builder| { - TimePeriod::with_days( - builder.get_number_of_days_until_auto_confirm(), - ) + builder.get_time_until_delayed_confirmation_is_callable() }) } @@ -433,12 +431,14 @@ impl SecurityShieldBuilder { self.set(|builder| builder.set_threshold(threshold)) } - pub fn set_time_period_until_auto_confirm( + pub fn set_time_until_delayed_confirmation_is_callable( &self, time_period: TimePeriod, ) -> &Self { self.set(|builder| { - builder.set_number_of_days_until_auto_confirm(time_period.days()) + builder.set_time_until_delayed_confirmation_is_callable( + time_period.days(), + ) }) } @@ -999,15 +999,17 @@ mod tests { } #[test] - fn test_get_time_period_until_auto_confirm() { + fn test_get_time_until_timed_confirmation_is_callable() { let sut = SUT::strict(); assert_eq!( - sut.get_time_period_until_auto_confirm(), + sut.get_time_until_timed_confirmation_is_callable(), TimePeriod::with_days(14) ); - sut.set_time_period_until_auto_confirm(TimePeriod::with_days(42)); + sut.set_time_until_delayed_confirmation_is_callable( + TimePeriod::with_days(42), + ); assert_eq!( - sut.get_time_period_until_auto_confirm(), + sut.get_time_until_timed_confirmation_is_callable(), TimePeriod::with_days(42) ); } @@ -1041,7 +1043,9 @@ mod tests { FactorSourceID::sample_device(), )) // Primary - .set_time_period_until_auto_confirm(TimePeriod::with_days(42)) + .set_time_until_delayed_confirmation_is_callable( + TimePeriod::with_days(42), + ) .add_factor_source_to_primary_threshold( FactorSourceID::sample_device(), ) @@ -1585,12 +1589,14 @@ mod test_invalid { } #[test] - fn number_of_auto_confirm_days_invalid() { + fn time_until_delayed_confirmation_is_callable_invalid() { let sut = valid(); - sut.set_time_period_until_auto_confirm(TimePeriod::with_days(0)); + sut.set_time_until_delayed_confirmation_is_callable( + TimePeriod::with_days(0), + ); assert_eq!( sut.validate().unwrap(), - SecurityShieldBuilderRuleViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero + SecurityShieldBuilderRuleViolation::NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero ); } diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs index 863455d7a..aebf6733a 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs @@ -53,8 +53,8 @@ impl AsShieldBuilderViolation for MatrixRolesInCombinationBasicViolation { match self { FactorSourceNotFoundInAnyRole => unreachable!("Cannot happen since this error is not returned by 'validate'/'build'."), - NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero => { - Some(SecurityShieldBuilderRuleViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero) + NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero => { + Some(SecurityShieldBuilderRuleViolation::NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero) } } } @@ -188,8 +188,8 @@ pub enum SecurityShieldBuilderRuleViolation { #[error("Shield name is invalid")] ShieldNameInvalid, - #[error("The number of days until auto confirm must be greater than zero")] - NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero, + #[error("The number of days until timed confirm is callable must be greater than zero")] + NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero, #[error("Recovery and confirmation factors overlap. No factor may be used in both the recovery and confirmation roles")] RecoveryAndConfirmationFactorsOverlap, diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_instances.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_instances.rs index 59e12180a..7d734a23a 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_instances.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_instances.rs @@ -287,7 +287,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { @@ -471,7 +474,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } }, "authenticationSigningFactorInstance": { "factorSourceID": { diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_source_ids.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_source_ids.rs index 382acb199..cd4c0c826 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_source_ids.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_source_ids.rs @@ -117,7 +117,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } } "#, @@ -184,7 +187,10 @@ mod tests { } ] }, - "numberOfDaysUntilAutoConfirm": 14 + "timeUntilDelayedConfirmationIsCallable": { + "value": 2, + "unit": "weeks" + } } } "#, diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_sources.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_sources.rs index 8391fb4e7..60283e99e 100644 --- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_sources.rs +++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_structure_of_factors/security_structure_of_factor_sources.rs @@ -104,7 +104,7 @@ impl From for MatrixOfFactorSourceIDs { ConfirmationRoleWithFactorSourceIds::from( value.confirmation_role, ), - value.number_of_days_until_auto_confirm, + value.time_until_delayed_confirmation_is_callable, ) } } diff --git a/crates/profile/models/security-structures/src/time_period.rs b/crates/profile/models/security-structures/src/time_period.rs index fc1e81b27..fa9b729ff 100644 --- a/crates/profile/models/security-structures/src/time_period.rs +++ b/crates/profile/models/security-structures/src/time_period.rs @@ -2,15 +2,30 @@ use crate::prelude::*; /// Time period expressed by a number of `TimePeriodUnit`. /// -/// Used to represent in the hosts UI the time period until the recovery role is auto confirmed -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +/// Used to represent in the hosts UI the time period until recovery can be confirmed with timed based confirmation +#[derive( + PartialEq, Eq, Clone, Copy, Debug, StdHash, Serialize, Deserialize, +)] pub struct TimePeriod { pub value: u16, pub unit: TimePeriodUnit, } impl TimePeriod { - pub fn with_days(value: u16) -> Self { + pub fn is_zero(&self) -> bool { + self.value == 0 + } + + pub fn in_minutes(&self) -> u32 { + match self.unit { + TimePeriodUnit::Days => self.value as u32 * MINUTES_PER_DAY, + TimePeriodUnit::Weeks => { + self.value as u32 * DAYS_PER_WEEK as u32 * MINUTES_PER_DAY + } + } + } + + pub const fn with_days(value: u16) -> Self { if (value % DAYS_PER_WEEK) == 0 { Self { value: value / DAYS_PER_WEEK, @@ -66,6 +81,21 @@ mod tests { assert_ne!(SUT::sample(), SUT::sample_other()); } + #[test] + fn is_zero() { + assert!(SUT::with_days(0).is_zero()); + } + + #[test] + fn day_in_minutes() { + assert_eq!(SUT::sample().in_minutes(), 1440); + } + + #[test] + fn week_in_minutes() { + assert_eq!(SUT::sample_other().in_minutes(), 10080); + } + #[test] fn days_conversion() { let mut sut = SUT::with_days(DAYS_PER_WEEK); @@ -82,4 +112,30 @@ mod tests { assert_eq!(sut.days(), 400); assert_eq!(sut.unit, TimePeriodUnit::Days); } + + #[test] + fn json_roundtrip_days() { + assert_eq_after_json_roundtrip( + &SUT::sample(), + r#" + { + "value": 1, + "unit": "days" + } + "#, + ); + } + + #[test] + fn json_roundtrip_weeks() { + assert_eq_after_json_roundtrip( + &SUT::sample_other(), + r#" + { + "value": 1, + "unit": "weeks" + } + "#, + ); + } } diff --git a/crates/profile/models/security-structures/src/time_period_unit.rs b/crates/profile/models/security-structures/src/time_period_unit.rs index 4232ed9a5..21b2f4ebd 100644 --- a/crates/profile/models/security-structures/src/time_period_unit.rs +++ b/crates/profile/models/security-structures/src/time_period_unit.rs @@ -3,9 +3,13 @@ use crate::prelude::*; /// Time period unit expressed in days, weeks, or years. /// /// Used to represent in the hosts UI the time period. -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive( + PartialEq, Eq, Clone, Copy, Debug, StdHash, Serialize, Deserialize, +)] pub enum TimePeriodUnit { + #[serde(rename = "days")] Days, + #[serde(rename = "weeks")] Weeks, } @@ -36,4 +40,10 @@ mod tests { fn inequality() { assert_ne!(SUT::sample(), SUT::sample_other()); } + + #[test] + fn json_roundtrip() { + assert_json_value_eq_after_roundtrip(&SUT::Days, json!("days")); + assert_json_value_eq_after_roundtrip(&SUT::Weeks, json!("weeks")); + } } diff --git a/crates/profile/models/supporting-types/Cargo.toml b/crates/profile/models/supporting-types/Cargo.toml index fea21d923..d8f0e6f59 100644 --- a/crates/profile/models/supporting-types/Cargo.toml +++ b/crates/profile/models/supporting-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-supporting-types" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/profile/models/supporting-types/src/abstract_securified_entity.rs b/crates/profile/models/supporting-types/src/abstract_securified_entity.rs index b99ca27e0..829412f5c 100644 --- a/crates/profile/models/supporting-types/src/abstract_securified_entity.rs +++ b/crates/profile/models/supporting-types/src/abstract_securified_entity.rs @@ -62,6 +62,13 @@ impl Into::::into(self.entity.address()) } + pub fn current_authentication_signing_factor_instance( + &self, + ) -> HierarchicalDeterministicFactorInstance { + self.securified_entity_control() + .authentication_signing_factor_instance() + } + pub fn veci(&self) -> Option { self.securified_entity_control() .veci() diff --git a/crates/profile/models/supporting-types/src/any_securified_entity.rs b/crates/profile/models/supporting-types/src/any_securified_entity.rs index 9fceb98bd..41a7a18c3 100644 --- a/crates/profile/models/supporting-types/src/any_securified_entity.rs +++ b/crates/profile/models/supporting-types/src/any_securified_entity.rs @@ -9,3 +9,69 @@ impl TryFrom for AnySecurifiedEntity { Self::new(value) } } + +impl AnySecurifiedEntity { + pub fn sample_account() -> Self { + SecurifiedAccount::sample().into() + } + + pub fn sample_account_other() -> Self { + SecurifiedAccount::sample_other().into() + } + + pub fn sample_persona() -> Self { + SecurifiedPersona::sample().into() + } + + pub fn sample_persona_other() -> Self { + SecurifiedPersona::sample_other().into() + } +} + +impl HasSampleValues for AnySecurifiedEntity { + fn sample() -> Self { + Self::sample_account() + } + + fn sample_other() -> Self { + Self::sample_persona() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = AnySecurifiedEntity; + + #[test] + fn equality() { + assert_eq!(SUT::sample(), SUT::sample()); + assert_eq!(SUT::sample_other(), SUT::sample_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::sample(), SUT::sample_other()); + } + + #[test] + fn hash() { + assert_eq!( + HashSet::::from_iter([ + SUT::sample_account(), + SUT::sample_account_other(), + SUT::sample_persona(), + SUT::sample_persona_other(), + // Duplicates should be removed + SUT::sample_account(), + SUT::sample_account_other(), + SUT::sample_persona(), + SUT::sample_persona_other(), + ]) + .len(), + 4 + ); + } +} diff --git a/crates/profile/models/supporting-types/src/lib.rs b/crates/profile/models/supporting-types/src/lib.rs index d0bc7f961..e206c846f 100644 --- a/crates/profile/models/supporting-types/src/lib.rs +++ b/crates/profile/models/supporting-types/src/lib.rs @@ -22,6 +22,7 @@ pub mod prelude { pub use crate::veci::*; pub use hierarchical_deterministic::prelude::*; + pub use prelude::prelude::*; pub use profile::prelude::*; pub(crate) use enum_as_inner::EnumAsInner; diff --git a/crates/profile/models/supporting-types/src/securified_account.rs b/crates/profile/models/supporting-types/src/securified_account.rs index d9b52a752..596e050f5 100644 --- a/crates/profile/models/supporting-types/src/securified_account.rs +++ b/crates/profile/models/supporting-types/src/securified_account.rs @@ -15,6 +15,12 @@ impl From for AnySecurifiedEntity { } } +impl From for Account { + fn from(value: SecurifiedAccount) -> Self { + value.entity + } +} + impl HasEntityKind for SecurifiedAccount { fn entity_kind() -> CAP26EntityKind { CAP26EntityKind::Account diff --git a/crates/profile/models/supporting-types/src/securified_persona.rs b/crates/profile/models/supporting-types/src/securified_persona.rs index d9b482925..0bf75bf5f 100644 --- a/crates/profile/models/supporting-types/src/securified_persona.rs +++ b/crates/profile/models/supporting-types/src/securified_persona.rs @@ -15,6 +15,12 @@ impl From for AnySecurifiedEntity { } } +impl From for Persona { + fn from(value: SecurifiedPersona) -> Self { + value.entity + } +} + impl HasEntityKind for SecurifiedPersona { fn entity_kind() -> CAP26EntityKind { CAP26EntityKind::Identity @@ -43,3 +49,32 @@ impl TryFrom for SecurifiedPersona { } } } + +impl HasSampleValues for SecurifiedPersona { + fn sample() -> Self { + Self::new(Persona::sample_at(2)).unwrap() + } + + fn sample_other() -> Self { + Self::new(Persona::sample_at(3)).unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = SecurifiedPersona; + + #[test] + fn equality() { + assert_eq!(SUT::sample(), SUT::sample()); + assert_eq!(SUT::sample_other(), SUT::sample_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::sample(), SUT::sample_other()); + } +} diff --git a/crates/profile/models/supporting-types/src/unsecurified_entity.rs b/crates/profile/models/supporting-types/src/unsecurified_entity.rs index 5ba614284..8fea1be29 100644 --- a/crates/profile/models/supporting-types/src/unsecurified_entity.rs +++ b/crates/profile/models/supporting-types/src/unsecurified_entity.rs @@ -48,12 +48,12 @@ where /// # Throws /// Throws if the entity is securified - pub fn new(entity: E) -> Result { + pub fn new>(entity: T) -> Result { match entity.security_state() { EntitySecurityState::Unsecured { value: unsecured_entity_control, } => Ok(Self::with_unsecured_entity_control( - entity, + entity.into(), unsecured_entity_control, )), EntitySecurityState::Securified { .. } => { @@ -129,11 +129,11 @@ impl TryFrom for UnsecurifiedPersona { impl HasSampleValues for AnyUnsecurifiedEntity { fn sample() -> Self { - Self::new(Account::sample().into()).unwrap() + Self::new(Account::sample()).unwrap() } fn sample_other() -> Self { - Self::new(Account::sample_other().into()).unwrap() + Self::new(Account::sample_other()).unwrap() } } diff --git a/crates/profile/traits/entity-by-address/Cargo.toml b/crates/profile/traits/entity-by-address/Cargo.toml index 15edb1274..70afdf160 100644 --- a/crates/profile/traits/entity-by-address/Cargo.toml +++ b/crates/profile/traits/entity-by-address/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "entity-by-address" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/sargon/Cargo.toml b/crates/sargon/Cargo.toml index 1903fcdfb..6cd964a7d 100644 --- a/crates/sargon/Cargo.toml +++ b/crates/sargon/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon" -version = "1.1.122" +version = "1.1.123" edition = "2021" resolver = "2" # features enabled in integration test diff --git a/crates/sargon/tests/vectors/main.rs b/crates/sargon/tests/vectors/main.rs index 8bf37bb63..d2a5f0280 100644 --- a/crates/sargon/tests/vectors/main.rs +++ b/crates/sargon/tests/vectors/main.rs @@ -1,12 +1,11 @@ -use sargon::prelude::*; - use core::fmt::Debug; +use sargon::prelude::*; use serde::Deserialize; use std::str::FromStr; #[cfg(test)] mod profile_snapshot_tests { - use prelude::fixture_vector; + use prelude::fixture_profiles; use super::*; @@ -17,7 +16,7 @@ mod profile_snapshot_tests { /// [doc]: https://radixdlt.atlassian.net/wiki/spaces/AT/pages/3251863610/CAP-36+WebRTC+Clients+Protocol #[test] fn v100_100() { - fixture_and_json::(fixture_vector!( + fixture_and_json::(fixture_profiles!( "only_plaintext_profile_snapshot_version_100" )) .expect("V100 Profile to deserialize"); @@ -592,7 +591,7 @@ mod slip10_tests { mod encrypted_profile_tests { use std::collections::HashSet; - use prelude::fixture_vector; + use prelude::fixture_profiles; use serde::Serialize; use super::*; @@ -744,7 +743,7 @@ mod encrypted_profile_tests { #[test] fn test_vectors() { - let fixture = fixture::(fixture_vector!( + let fixture = fixture::(fixture_profiles!( "multi_profile_snapshots_test_version_100_patch_after_app_version_120" )) .expect("Encrypted Profile tests"); @@ -756,13 +755,13 @@ mod encrypted_profile_tests { #[cfg(test)] mod dapp_to_wallet_interaction_tests { use super::*; - use prelude::fixture_vector; + use prelude::fixture_interaction; use serde_json::Value; #[test] fn test_vector() { let decoded_wallet_interactions = - fixture::>(fixture_vector!( + fixture::>(fixture_interaction!( "wallet_interactions_dapp_to_wallet" )) .expect("wallet_interactions_dapp_to_wallet fixture"); @@ -992,9 +991,9 @@ mod dapp_to_wallet_interaction_tests { pretty_assertions::assert_eq!(fixture, expected); } - let raw_wallet_interactions = fixture::>(fixture_vector!( - "wallet_interactions_dapp_to_wallet" - )) + let raw_wallet_interactions = fixture::>( + fixture_interaction!("wallet_interactions_dapp_to_wallet"), + ) .expect("wallet_interactions_dapp_to_wallet fixture"); let encoded_interactions = @@ -1014,7 +1013,7 @@ mod dapp_to_wallet_interaction_tests { mod wallet_to_dapp_interaction_tests { use super::*; - use prelude::fixture_vector; + use prelude::fixture_interaction; use serde_json::Value; #[test] @@ -1280,7 +1279,7 @@ mod wallet_to_dapp_interaction_tests { let encoded = serde_json::to_string(&responses).unwrap(); let serde_value: Vec = serde_json::from_str(&encoded).unwrap(); - let fixture = fixture::>(fixture_vector!( + let fixture = fixture::>(fixture_interaction!( "wallet_interactions_wallet_to_dapp" )) .expect("wallet_interactions_wallet_to_dapp fixture"); diff --git a/crates/system/clients/clients/Cargo.toml b/crates/system/clients/clients/Cargo.toml index cbe2b91eb..29d024870 100644 --- a/crates/system/clients/clients/Cargo.toml +++ b/crates/system/clients/clients/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clients" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/system/clients/http/Cargo.toml b/crates/system/clients/http/Cargo.toml index c6020d752..f6296b0df 100644 --- a/crates/system/clients/http/Cargo.toml +++ b/crates/system/clients/http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "http-client" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/drivers/Cargo.toml b/crates/system/drivers/Cargo.toml index d094c1848..4dabb41b3 100644 --- a/crates/system/drivers/Cargo.toml +++ b/crates/system/drivers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drivers" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/system/interactors/Cargo.toml b/crates/system/interactors/Cargo.toml index f48ccc6e6..b0ad71d37 100644 --- a/crates/system/interactors/Cargo.toml +++ b/crates/system/interactors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "interactors" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/accounts/Cargo.toml b/crates/system/os/accounts/Cargo.toml index a7e22cb60..b2f988316 100644 --- a/crates/system/os/accounts/Cargo.toml +++ b/crates/system/os/accounts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-accounts" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/derive-public-keys/Cargo.toml b/crates/system/os/derive-public-keys/Cargo.toml index d0db32f8c..48e91b633 100644 --- a/crates/system/os/derive-public-keys/Cargo.toml +++ b/crates/system/os/derive-public-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-derive-public-keys" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/factors/Cargo.toml b/crates/system/os/factors/Cargo.toml index 65cdf4420..670abb019 100644 --- a/crates/system/os/factors/Cargo.toml +++ b/crates/system/os/factors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-factors" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_security_shield_interaction.rs b/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_security_shield_interaction.rs index 30e6d19e2..3566aa566 100644 --- a/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_security_shield_interaction.rs +++ b/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_security_shield_interaction.rs @@ -3,6 +3,35 @@ use radix_connect::DappToWalletInteractionBatchOfTransactions; #[async_trait::async_trait] pub trait OsApplySecurityShieldInteraction { + /// For every entity in the given set of addresses, we use FactorInstancesProvider + /// to create `SecurityStructureOfFactorInstances` based on the security shield + /// loaded by the given `security_shield_id`. We update Profile to set + /// a provisional security config with the derived factors. + /// + /// We then create one TransactionManifest for each entity, if the entity + /// is unsecurified it will be a Manifest which calls "securify" on the + /// component and creates an AccessController for it. If the entity is already + /// securified, we will create a Manifest which uses default `RolesExercisableInTransactionManifestCombination` + /// to update the security config. + /// + /// These manifests are not fully valid yet - we need to set a payer of XRD + /// vault top up and TX fee - which uses different logic depending on if + /// the entity applying the shield is securified or not. If it is securified + /// we will need to lock fee against the XRD vault of the AccessController - + /// if the entity is unsecurified we will need to lock fee against the account + /// address if it is an account - if it is a Persona another account - securified + /// or not - will need to be used to pay TX fee. + /// + /// Host should present these manifests to the user for approval, and then + /// display necessary input UI components for payer and fee locking - and then + /// host need to tell Sargon to create many more manifest for each securified + /// entity, `RolesExercisableInTransactionManifestCombination::all() - 1` more + /// manifests need to be created and set payer and fee locking for each of them. + /// + /// When user slides to sign - Sargon will try to batch sign each kind of manifest + /// based on `RolesExercisableInTransactionManifestCombination` for the securified + /// entities - and for the unsecurified entities the Primary role will always + /// be used. async fn make_interaction_for_applying_security_shield( &self, security_shield_id: SecurityStructureID, @@ -30,28 +59,198 @@ impl OsApplySecurityShieldInteraction for SargonOS { .map(|e| { let provisional = e.entity.get_provisional().expect("Entity should have a provisional config set since we applied shield above"); let derived = provisional.as_factor_instances_derived().expect("Should have derived factors"); - let input = TransactionManifestApplySecurityShieldUnsecurifiedInput::new(derived.clone()); TransactionManifest::apply_security_shield_for_unsecurified_entity( - e, - input, - ) - }).collect::>>()?; + e.clone(), + derived.clone() + ).map(UnvalidatedTransactionManifest::from) + }).collect::>>()?; let manifests_for_securified = entities_with_provisional .securified_erased() .iter() .map(|e| { let provisional = e.entity.get_provisional().expect("Entity should have a provisional config set since we applied shield above"); - let _derived = provisional.as_factor_instances_derived().expect("Should have derived factors"); - todo!("Implement TransactionManifest::apply_security_shield_for_securified_entity") - }).collect::>>()?; + let derived = provisional.as_factor_instances_derived().expect("Should have derived factors"); + TransactionManifest::apply_security_shield_for_securified_entity( + e.clone(), + derived.clone(), + RolesExercisableInTransactionManifestCombination::manifest_end_user_gets_to_preview() + ) + .map(UnvalidatedTransactionManifest::from).unwrap() + }).collect_vec(); Ok(DappToWalletInteractionBatchOfTransactions::new( manifests_for_unsecurified .iter() .chain(manifests_for_securified.iter()) - .cloned() - .map(UnvalidatedTransactionManifest::from), + .cloned(), )) } } + +#[cfg(test)] +mod tests { + use prelude::fixture_interaction; + + use super::*; + + #[actix_rt::test] + async fn test_make_interaction_for_applying_security_shield() { + // ARRANGE + let (os, shield_id, addresses_of_mixed_entities_sec_unsec) = { + let os = SargonOS::fast_boot_bdfs_and_interactor( + MnemonicWithPassphrase::sample_device_other(), + None, + false, + ) + .await; + let shield = add_unsafe_shield_with_matrix_with_fixed_metadata( + &os, + SecurityStructureMetadata::sample(), + ) + .await + .unwrap(); + let shield_id = shield.id(); + let network = NetworkID::Mainnet; + let account = os + .create_and_save_new_account_with_main_bdfs( + network, + DisplayName::sample(), + ) + .await + .unwrap(); + let persona = os + .create_and_save_new_persona_with_main_bdfs( + network, + DisplayName::sample_other(), + None, + ) + .await + .unwrap(); + + os.apply_security_shield_with_id_to_entities( + shield_id, + IndexSet::from_iter([ + AddressOfAccountOrPersona::from(account.address()), + AddressOfAccountOrPersona::from(persona.address()), + ]), + ) + .await + .unwrap(); + + // Dummy impl of securifying entities + let (securified_account, securified_persona) = { + let mut account = + os.account_by_address(account.address()).unwrap(); + let mut persona = + os.persona_by_address(persona.address()).unwrap(); + + let mut account_security_structure_of_instances = account + .get_provisional() + .unwrap() + .as_factor_instances_derived() + .unwrap() + .clone(); + + // Here we ensure that we test that we reuse the existing ROLA key for the persona below, but not for this account, i.e. the existing ROLA key of this account will mismatch that of the shield. + account_security_structure_of_instances + .authentication_signing_factor_instance = + HierarchicalDeterministicFactorInstance::sample_auth_signing(); + assert_ne!( + FactorSourceID::from( + account_security_structure_of_instances + .authentication_signing_factor_instance + .factor_source_id + ), + shield.authentication_signing_factor + ); + + let account_secured_control = SecuredEntityControl::new( + account + .clone() + .security_state() + .as_unsecured() + .unwrap() + .transaction_signing + .clone(), + AccessControllerAddress::sample_mainnet(), + account_security_structure_of_instances, + ) + .unwrap(); + account + .set_security_state(EntitySecurityState::Securified { + value: account_secured_control, + }) + .unwrap(); + os.update_account(account.clone()).await.unwrap(); + + let persona_security_structure_of_instances = persona + .get_provisional() + .unwrap() + .as_factor_instances_derived() + .unwrap() + .clone(); + let persona_secured_control = SecuredEntityControl::new( + persona + .clone() + .security_state() + .as_unsecured() + .unwrap() + .transaction_signing + .clone(), + AccessControllerAddress::sample_mainnet_other(), + persona_security_structure_of_instances, + ) + .unwrap(); + persona + .set_security_state(EntitySecurityState::Securified { + value: persona_secured_control, + }) + .unwrap(); + os.update_persona(persona.clone()).await.unwrap(); + + (account, persona) + }; + + let account = os + .create_and_save_new_account_with_main_bdfs( + network, + DisplayName::sample(), + ) + .await + .unwrap(); + let persona = os + .create_and_save_new_persona_with_main_bdfs( + network, + DisplayName::sample_other(), + None, + ) + .await + .unwrap(); + + ( + os, + shield_id, + IndexSet::from_iter([ + AddressOfAccountOrPersona::from(account.address()), + persona.address().into(), + securified_account.address().into(), + securified_persona.address().into(), + ]), + ) + }; + + // ACT + let interaction = { + os.make_interaction_for_applying_security_shield( + shield_id, + addresses_of_mixed_entities_sec_unsec.clone(), + ) + .await + .unwrap() + }; + let fixture_json = + fixture_interaction!("wallet_interaction_batch_of_transactions"); + assert_eq_after_json_roundtrip(&interaction, fixture_json); + } +} diff --git a/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_shield.rs b/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_shield.rs index 0eaf4a505..54de073a6 100644 --- a/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_shield.rs +++ b/crates/system/os/factors/src/apply_security_shield/sargon_os_apply_shield.rs @@ -367,56 +367,72 @@ impl OsShieldApplying for SargonOS { } #[cfg(test)] -mod tests { - - use super::*; - - fn unsafe_shield_with_bdfs( - bdfs: &FactorSource, - ) -> SecurityStructureOfFactorSourceIDs { - let id = bdfs.factor_source_id(); - - // This is an invalid shield, but it's just for testing - let matrix = unsafe { - MatrixOfFactorSourceIds::unbuilt_with_roles_and_days( - PrimaryRoleWithFactorSourceIDs::unbuilt_with_factors( - Threshold::zero(), - [], - [id], - ), - RecoveryRoleWithFactorSourceIDs::unbuilt_with_factors( - Threshold::zero(), - [], - [id], - ), - ConfirmationRoleWithFactorSourceIDs::unbuilt_with_factors( - Threshold::zero(), - [], - [id], - ), - 14, - ) - }; - SecurityStructureOfFactorSourceIds::new( - DisplayName::new("Invalid Shield").unwrap(), - matrix, - id, +pub(crate) fn unsafe_shield_with_bdfs( + bdfs: &FactorSource, +) -> SecurityStructureOfFactorSourceIDs { + let id = bdfs.factor_source_id(); + + // This is an invalid shield, but it's just for testing + let matrix = unsafe { + MatrixOfFactorSourceIds::unbuilt_with_roles_and_days( + PrimaryRoleWithFactorSourceIDs::unbuilt_with_factors( + Threshold::zero(), + [], + [id], + ), + RecoveryRoleWithFactorSourceIDs::unbuilt_with_factors( + Threshold::zero(), + [], + [id], + ), + ConfirmationRoleWithFactorSourceIDs::unbuilt_with_factors( + Threshold::zero(), + [], + [id], + ), + TimePeriod::with_days(14), ) - } + }; + SecurityStructureOfFactorSourceIds::new( + DisplayName::new("Invalid Shield").unwrap(), + matrix, + id, + ) +} - async fn add_unsafe_shield_with_matrix( - os: &SargonOS, - ) -> Result { - let bdsf = os.main_bdfs()?; - let shield_of_ids = unsafe_shield_with_bdfs(&bdsf.into()); - os.add_security_structure_of_factor_source_ids(&shield_of_ids) - .await?; - Ok(shield_of_ids) +#[cfg(test)] +pub(crate) async fn add_unsafe_shield_with_matrix_with_fixed_metadata( + os: &SargonOS, + fixed_metadata: impl Into>, +) -> Result { + let bdsf = os.main_bdfs()?; + let mut shield_of_ids = unsafe_shield_with_bdfs(&bdsf.into()); + if let Some(fixed_metadata) = fixed_metadata.into() { + shield_of_ids.metadata = fixed_metadata; } + os.add_security_structure_of_factor_source_ids(&shield_of_ids) + .await?; + Ok(shield_of_ids) +} - async fn add_unsafe_shield(os: &SargonOS) -> Result { - add_unsafe_shield_with_matrix(os).await.map(|s| s.id()) - } +#[cfg(test)] +pub(crate) async fn add_unsafe_shield_with_matrix( + os: &SargonOS, +) -> Result { + add_unsafe_shield_with_matrix_with_fixed_metadata(os, None).await +} + +#[cfg(test)] +pub(crate) async fn add_unsafe_shield( + os: &SargonOS, +) -> Result { + add_unsafe_shield_with_matrix(os).await.map(|s| s.id()) +} + +#[cfg(test)] +mod tests { + + use super::*; #[actix_rt::test] async fn test_apply_security_shield_with_id_to_unsecurified_entities_only() diff --git a/crates/system/os/factors/src/lib.rs b/crates/system/os/factors/src/lib.rs index 532283d93..d167bf328 100644 --- a/crates/system/os/factors/src/lib.rs +++ b/crates/system/os/factors/src/lib.rs @@ -18,8 +18,6 @@ pub mod prelude { pub use profile_logic::prelude::*; pub use sargon_os::prelude::*; - pub(crate) use std::collections::HashSet; - #[cfg(test)] pub(crate) use interactors::prelude::*; } diff --git a/crates/system/os/factors/src/test_instances_provider.rs b/crates/system/os/factors/src/test_instances_provider.rs index 2f4ac1675..7875050bf 100644 --- a/crates/system/os/factors/src/test_instances_provider.rs +++ b/crates/system/os/factors/src/test_instances_provider.rs @@ -404,7 +404,7 @@ async fn cache_is_unchanged_in_case_of_failure() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -565,7 +565,7 @@ async fn test_assert_factor_instances_invalid() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -916,7 +916,7 @@ async fn test_securified_accounts() { [], [bdfs.clone(), ledger.clone(), arculus.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1066,7 +1066,7 @@ async fn test_securified_accounts() { [], [password.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1210,7 +1210,7 @@ async fn securify_accounts_when_cache_is_half_full_single_factor_source() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1380,7 +1380,7 @@ async fn securify_accounts_when_cache_is_half_full_multiple_factor_sources() { [], [bdfs.clone(), ledger.clone(), arculus.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1632,7 +1632,7 @@ async fn securify_personas_when_cache_is_half_full_single_factor_source() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1780,7 +1780,7 @@ async fn create_single_account() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -1879,7 +1879,7 @@ async fn securified_personas() { [], [bdfs.clone(), ledger.clone(), arculus.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2032,7 +2032,7 @@ async fn securified_personas() { [], [password.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2208,7 +2208,7 @@ async fn securified_all_accounts_next_veci_does_not_start_at_zero() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2421,7 +2421,7 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { [], [bdfs.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2455,8 +2455,6 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { .await .unwrap(); - println!("🔮🔮🔮🔮"); - for ui in updated_instances { println!( "{:?}", @@ -2478,7 +2476,6 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { .collect_vec() ); } - println!("🔮🔮🔮🔮"); assert!( !derivation_outcome.derived_any_new_instance_for_any_factor_source(), @@ -2577,7 +2574,7 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { [], [bdfs.clone(), arculus.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2648,7 +2645,7 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { [], [bdfs.clone(), ledger.clone()], ), - 1, + TimePeriod::with_days(1), ) }; @@ -2762,7 +2759,7 @@ async fn securified_accounts_and_personas_mixed_asymmetric_indices() { [], [bdfs.clone(), ledger.clone(), arculus.clone()], ), - 1, + TimePeriod::with_days(1), ) }; diff --git a/crates/system/os/os/Cargo.toml b/crates/system/os/os/Cargo.toml index 95c4bb854..d7aaf100b 100644 --- a/crates/system/os/os/Cargo.toml +++ b/crates/system/os/os/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/os/src/lib.rs b/crates/system/os/os/src/lib.rs index 7facec218..7b240450c 100644 --- a/crates/system/os/os/src/lib.rs +++ b/crates/system/os/os/src/lib.rs @@ -38,8 +38,6 @@ pub mod prelude { pub(crate) use signing_traits::prelude::*; pub(crate) use sub_systems::prelude::*; - pub(crate) use std::collections::HashSet; - #[cfg(test)] pub(crate) use testing::*; diff --git a/crates/system/os/security-center/Cargo.toml b/crates/system/os/security-center/Cargo.toml index e52c2a162..c440199ed 100644 --- a/crates/system/os/security-center/Cargo.toml +++ b/crates/system/os/security-center/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-security-center" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/signing/Cargo.toml b/crates/system/os/signing/Cargo.toml index 7cd91c5cf..4654a9059 100644 --- a/crates/system/os/signing/Cargo.toml +++ b/crates/system/os/signing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-signing" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/os/transaction/Cargo.toml b/crates/system/os/transaction/Cargo.toml index 571d68b78..9219db8d6 100644 --- a/crates/system/os/transaction/Cargo.toml +++ b/crates/system/os/transaction/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-os-transaction" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/profile-state-holder/Cargo.toml b/crates/system/profile-state-holder/Cargo.toml index a6f55a501..2d342ed7d 100644 --- a/crates/system/profile-state-holder/Cargo.toml +++ b/crates/system/profile-state-holder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "profile-state-holder" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/system/sub-systems/Cargo.toml b/crates/system/sub-systems/Cargo.toml index 936871f29..4d324c292 100644 --- a/crates/system/sub-systems/Cargo.toml +++ b/crates/system/sub-systems/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sub-systems" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/transaction/foundation/Cargo.toml b/crates/transaction/foundation/Cargo.toml index 3188743e0..ccc034fe7 100644 --- a/crates/transaction/foundation/Cargo.toml +++ b/crates/transaction/foundation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "transaction-foundation" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/transaction/manifests/Cargo.toml b/crates/transaction/manifests/Cargo.toml index f5a31f41c..1ab330a60 100644 --- a/crates/transaction/manifests/Cargo.toml +++ b/crates/transaction/manifests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "manifests" -version = "1.1.122" +version = "1.1.123" edition = "2021" @@ -33,6 +33,7 @@ sbor = { workspace = true } # === EXTERNAL DEPENDENCIES === derive_more = { workspace = true } enum-as-inner = { workspace = true } +enum-iterator = { workspace = true } itertools = { workspace = true } paste = { workspace = true } pretty_assertions = { workspace = true } diff --git a/crates/transaction/manifests/src/lib.rs b/crates/transaction/manifests/src/lib.rs index 45ff0b5a8..cbddf100c 100644 --- a/crates/transaction/manifests/src/lib.rs +++ b/crates/transaction/manifests/src/lib.rs @@ -30,6 +30,7 @@ pub mod prelude { pub use gateway_models::prelude::*; pub use hierarchical_deterministic::prelude::*; pub use metadata::prelude::*; + pub use prelude::prelude::*; pub use profile::prelude::*; pub use std::str::FromStr; @@ -158,9 +159,6 @@ pub mod prelude { pub(crate) use serde::{Deserialize, Serialize}; pub(crate) use std::collections::BTreeMap; - - #[cfg(test)] - pub(crate) use std::collections::HashSet; } pub use prelude::*; diff --git a/crates/transaction/manifests/src/manifest_builder_from_manifest.rs b/crates/transaction/manifests/src/manifest_builder_from_manifest.rs index 27c286068..ae933d6a3 100644 --- a/crates/transaction/manifests/src/manifest_builder_from_manifest.rs +++ b/crates/transaction/manifests/src/manifest_builder_from_manifest.rs @@ -2,7 +2,35 @@ use radix_transactions::prelude::ManifestBuilder; use crate::prelude::*; -pub trait BuilderFromManifest { +pub trait BuilderExtendWithInstructions: Sized { + fn extend_builder_with_instructions( + self, + instructions: impl IntoIterator, + ) -> ManifestBuilder; + + fn extend_builder_with_manifest( + self, + manifest: TransactionManifest, + ) -> ManifestBuilder { + Self::extend_builder_with_instructions( + self, + manifest.instructions().clone(), + ) + } +} + +impl BuilderExtendWithInstructions for ManifestBuilder { + fn extend_builder_with_instructions( + self, + instructions: impl IntoIterator, + ) -> ManifestBuilder { + instructions.into_iter().fold(self, |builder, instruction| { + builder.add_instruction_advanced(instruction).0 + }) + } +} + +pub trait BuilderFromManifest: BuilderExtendWithInstructions { fn with_instructions( instructions: impl IntoIterator, ) -> ManifestBuilder; @@ -16,11 +44,9 @@ impl BuilderFromManifest for ManifestBuilder { fn with_instructions( instructions: impl IntoIterator, ) -> ManifestBuilder { - instructions.into_iter().fold( + Self::extend_builder_with_instructions( ManifestBuilder::new(), - |builder, instruction| { - builder.add_instruction_advanced(instruction).0 - }, + instructions, ) } } diff --git a/crates/transaction/manifests/src/manifests_security_shield/access_controller_factors_and_time_input.rs b/crates/transaction/manifests/src/manifests_security_shield/access_controller_factors_and_time_input.rs new file mode 100644 index 000000000..29f64db13 --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/access_controller_factors_and_time_input.rs @@ -0,0 +1,106 @@ +use crate::prelude::*; +use radix_engine_interface::blueprints::access_controller::{ + AccessControllerInitiateRecoveryAsPrimaryInput as ScryptoAccessControllerInitiateRecoveryAsPrimaryInput, + AccessControllerInitiateRecoveryAsRecoveryInput as ScryptoAccessControllerInitiateRecoveryAsRecoveryInput, + AccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput as ScryptoAccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput, + AccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput as ScryptoAccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput, + AccessControllerTimedConfirmRecoveryInput as ScryptoAccessControllerTimedConfirmRecoveryInput, +}; + +/// An ephemeral DTO that is used to create the input for the access controller +/// methods that require factors and time - which we create from a +/// `SecurityStructureOfFactorInstances` +#[derive(Debug, Clone)] +pub struct AccessControllerFactorsAndTimeInput { + /// RuleSet is Scrypto representation of the security structure's + /// MatrixOfFactors + rule_set: ScryptoRuleSet, + /// The timed recovery delay in minutes we get from `SecurityStructureOfFactorInstances`. + timed_recovery_delay_in_minutes: u32, +} + +impl AccessControllerFactorsAndTimeInput { + pub fn new( + security_structure_of_factor_instances: &SecurityStructureOfFactorInstances, + ) -> Self { + let rule_set = ScryptoRuleSet::from( + security_structure_of_factor_instances + .matrix_of_factors + .clone(), + ); + + let timed_recovery_delay_in_minutes = + security_structure_of_factor_instances + .timed_recovery_delay_in_minutes(); + + Self { + rule_set, + timed_recovery_delay_in_minutes, + } + } +} + +impl From<&AccessControllerFactorsAndTimeInput> + for ScryptoAccessControllerInitiateRecoveryAsRecoveryInput +{ + fn from(value: &AccessControllerFactorsAndTimeInput) -> Self { + Self { + rule_set: value.rule_set.clone(), + timed_recovery_delay_in_minutes: Some( + value.timed_recovery_delay_in_minutes, + ), + } + } +} + +impl From<&AccessControllerFactorsAndTimeInput> + for ScryptoAccessControllerInitiateRecoveryAsPrimaryInput +{ + fn from(value: &AccessControllerFactorsAndTimeInput) -> Self { + Self { + rule_set: value.rule_set.clone(), + timed_recovery_delay_in_minutes: Some( + value.timed_recovery_delay_in_minutes, + ), + } + } +} + +impl From<&AccessControllerFactorsAndTimeInput> + for ScryptoAccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput +{ + fn from(value: &AccessControllerFactorsAndTimeInput) -> Self { + Self { + rule_set: value.rule_set.clone(), + timed_recovery_delay_in_minutes: Some( + value.timed_recovery_delay_in_minutes, + ), + } + } +} + +impl From<&AccessControllerFactorsAndTimeInput> + for ScryptoAccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput +{ + fn from(value: &AccessControllerFactorsAndTimeInput) -> Self { + Self { + rule_set: value.rule_set.clone(), + timed_recovery_delay_in_minutes: Some( + value.timed_recovery_delay_in_minutes, + ), + } + } +} + +impl From<&AccessControllerFactorsAndTimeInput> + for ScryptoAccessControllerTimedConfirmRecoveryInput +{ + fn from(value: &AccessControllerFactorsAndTimeInput) -> Self { + Self { + rule_set: value.rule_set.clone(), + timed_recovery_delay_in_minutes: Some( + value.timed_recovery_delay_in_minutes, + ), + } + } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/confirm_timed_recovery.rs b/crates/transaction/manifests/src/manifests_security_shield/confirm_timed_recovery.rs new file mode 100644 index 000000000..a6892f86d --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/confirm_timed_recovery.rs @@ -0,0 +1,27 @@ +use crate::prelude::*; + +// use radix_engine_interface::blueprints::access_controller::{ +// AccessControllerTimedConfirmRecoveryInput as ScryptoAccessControllerTimedConfirmRecoveryInput, +// ACCESS_CONTROLLER_TIMED_CONFIRM_RECOVERY_IDENT as SCRYPTO_ACCESS_CONTROLLER_TIMED_CONFIRM_RECOVERY_IDENT, +// }; + +pub trait TransactionManifestConfirmTimedRecovery { + /// TBD + /// TODO: Figure out how to do this... + /// since `AccessControllerTimedConfirmRecoveryInput` need the input of + /// the factors and time which was used to start recovery - which could not + /// be quick confirmed. We need to figure out how we best represent this + /// in Profile. Perhaps a new variant on ProvisionalSecurityConfig? Something + /// like: + /// `WaitingForTimedRecovery(SecurityStructureOfFactorInstances)` + fn confirm_timed_recovery() -> Result; + // { + // builder.call_method( + // access_controller, + // SCRYPTO_ACCESS_CONTROLLER_TIMED_CONFIRM_RECOVERY_IDENT, + // ScryptoAccessControllerTimedConfirmRecoveryInput::from( + // factors_and_time, + // ), + // ); + // } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/lock_fee_against_xrd_vault_of_access_controller.rs b/crates/transaction/manifests/src/manifests_security_shield/lock_fee_against_xrd_vault_of_access_controller.rs new file mode 100644 index 000000000..f9fd980a3 --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/lock_fee_against_xrd_vault_of_access_controller.rs @@ -0,0 +1,62 @@ +use profile_supporting_types::AnySecurifiedEntity; +use radix_engine_interface::blueprints::access_controller::{ + AccessControllerLockRecoveryFeeInput as ScryptoAccessControllerLockRecoveryFeeInput, + ACCESS_CONTROLLER_LOCK_RECOVERY_FEE_IDENT as SCRYPTO_ACCESS_CONTROLLER_LOCK_RECOVERY_FEE_IDENT, +}; +use radix_transactions::prelude::ManifestBuilder; + +use crate::prelude::*; + +impl TransactionManifestLockFeeAgainstXrdVaultOfAccessController + for TransactionManifest +{ +} + +pub trait TransactionManifestLockFeeAgainstXrdVaultOfAccessController { + /// Locks transaction fee against the XRD vault of the access controller of + /// `entity_applying_shield` - either AC of an Account or of a Persona. + /// + /// We need to call this later when we have made a preview/dry-run of the + /// `manifest` to get the actual fee to lock. + /// + /// `manifest` was produced by `apply_security_shield_for_securified_entity`. + /// + /// In fact we will be locking fee for 6 flavours of transaction manifest + /// which updates the security shield of an entity, as returned by + /// `RolesExercisableInTransactionManifestCombination::all()`, and we could try to + /// be smart and run preview of each six to get a minimal fee per manifest, + /// but we will avoid that complexity. + /// + /// Only relevant for securified entities - since it is only securified entities + /// which have an access controller to lock against. + fn modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller( + manifest: TransactionManifest, + fee: Decimal192, + // TODO: remove `entity_applying_shield`, this should be read out from the manifest in a throwing function, `manifest.get_address_of_entity_applying_shield()` or similar which Omar need to provide us with, oh well we need the account here, so elsewhere, in SargonOS where we have access to Profile we would call `manifest.get_address_of_entity_applying_shield` and then lookup the entity. + entity_applying_shield: impl Into, + ) -> TransactionManifest { + let mut builder = ManifestBuilder::new(); + let entity_applying_shield = entity_applying_shield.into(); + let access_controller_address = entity_applying_shield + .securified_entity_control + .access_controller_address; + + // Lock fee against XRD vault of the access controller + // put this instruction at index 0 + builder = builder.call_method( + access_controller_address.scrypto(), + SCRYPTO_ACCESS_CONTROLLER_LOCK_RECOVERY_FEE_IDENT, + ScryptoAccessControllerLockRecoveryFeeInput { + amount: ScryptoDecimal192::from(fee), + }, + ); + + // ... then append all instructions from the original manifest + builder = builder.extend_builder_with_manifest(manifest); + + TransactionManifest::sargon_built( + builder, + entity_applying_shield.entity.network_id(), + ) + } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_securified_entity.rs b/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_securified_entity.rs new file mode 100644 index 000000000..ee302c7cf --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_securified_entity.rs @@ -0,0 +1,274 @@ +#![allow(dead_code)] +use crate::prelude::*; +use std::ops::Deref; + +use profile_supporting_types::AnySecurifiedEntity; + +pub trait TransactionManifestSecurifySecurifiedEntity: + TransactionManifestSetRolaKey +{ + fn apply_security_shield_for_securified_entity( + securified_entity: impl Into, + security_structure_of_factor_instances: + SecurityStructureOfFactorInstances, + roles_combination: RolesExercisableInTransactionManifestCombination, + ) -> Option; +} + +impl TransactionManifestSecurifySecurifiedEntity for TransactionManifest { + /// Updates the security shield of a securified entity to `security_structure_of_factor_instances`. + /// + /// Also conditionally updates the Rola key of the entity - if it is new. + /// + /// Later once we have got a preview from Gateway - we will need to call: + /// * `modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller` + /// + /// And when we know the fee we can calculate how much to top up the XRD vault of the AccessController + /// and call + /// * `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_securified_account_paid_by_account` + /// + /// For timed confirmation - much later (`timed_recovery_delay_in_minutes` later ) the + /// host app will need to call `confirm_timed_recovery` + fn apply_security_shield_for_securified_entity( + securified_entity: impl Into, + security_structure_of_factor_instances: + SecurityStructureOfFactorInstances, + roles_combination: RolesExercisableInTransactionManifestCombination, + ) -> Option { + let securified_entity = securified_entity.into(); + let kind = roles_combination; + let entity_address = securified_entity.entity.address(); + + security_structure_of_factor_instances + .assert_has_entity_kind(entity_address.get_entity_kind()).expect("Shouldn't have used wrong FactorInstance for entity - apply_security_shield_with_id_to_entities has some bug."); + + let mut builder = ScryptoTransactionManifestBuilder::new(); + + let set_rola = |builder: ScryptoTransactionManifestBuilder| -> ScryptoTransactionManifestBuilder { + TransactionManifest::set_rola_key( + builder, + &security_structure_of_factor_instances + .authentication_signing_factor_instance, + &entity_address, + ) + }; + + let order_of_instruction_setting_rola = kind + .order_of_instruction_setting_rola( + &security_structure_of_factor_instances, + &securified_entity, + ); + + let access_controller_address = securified_entity + .securified_entity_control + .access_controller_address; + + let factors_and_time_input = &AccessControllerFactorsAndTimeInput::new( + &security_structure_of_factor_instances, + ); + + match order_of_instruction_setting_rola { + OrderOfInstructionSettingRolaKey::BeforeInitRecovery => { + builder = set_rola(builder); + } + OrderOfInstructionSettingRolaKey::AfterQuickConfirm | OrderOfInstructionSettingRolaKey::NotNeeded | OrderOfInstructionSettingRolaKey::MustSetInFutureTxForConfirmRecovery => { + // Do nothing for now + } + } + + // INITIATE RECOVERY + let (init_method, init_input) = + kind.input_for_initialization(factors_and_time_input); + builder = builder.call_method( + access_controller_address.scrypto(), + init_method, + (init_input.deref(),), + ); + + // QUICK CONFIRM RECOVERY - Only if we can exercise the confirmation role explicitly. + if let Some((confirm_method, confirm_input)) = + kind.input_for_quick_confirm(factors_and_time_input) + { + builder = builder.call_method( + access_controller_address.scrypto(), + confirm_method, + (confirm_input.deref(),), + ); + } + + match order_of_instruction_setting_rola { + OrderOfInstructionSettingRolaKey::AfterQuickConfirm => { + builder = set_rola(builder); + } + OrderOfInstructionSettingRolaKey::BeforeInitRecovery | OrderOfInstructionSettingRolaKey::NotNeeded => { + // nothing to do + } OrderOfInstructionSettingRolaKey::MustSetInFutureTxForConfirmRecovery => { + info!("Do not forget to set Rola key in future transaction for Confirm Recovery"); + } + } + + let manifest = TransactionManifest::sargon_built( + builder, + securified_entity.network_id(), + ); + + // N.B. + // We will not lock fee against the XRD vault yet - we will do that + // later when we have made a preview/dry-run of the `manifest` to get + // the estimated fee to lock, by calling `modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller` + // + // Furthermore: + // We do NOT top of XRD vault of AccessController - yet! + // Host will need to call the function: + // `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_securified_account_paid_by_account` + // after user has selected account to pay in wallet GUI. And also call + // `modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller` + + Some(manifest) + } +} + +#[cfg(test)] +mod tests { + #![allow(non_snake_case)] + + use prelude::fixture_rtm; + use profile_supporting_types::{SecurifiedAccount, SecurifiedPersona}; + use radix_transactions::manifest::{ + CallMetadataMethod, CallMethod, ManifestInstruction, + }; + use sbor::SborEnum; + + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = TransactionManifest; + + #[test] + fn update_shield_of_securified_account_with_top_up_where_payer_is_entity_applying_shield( + ) { + let entity_applying_shield = SecurifiedAccount::sample(); + assert_eq!(entity_applying_shield.securified_entity_control.access_controller_address.to_string(), "accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g"); + + let manifest = SUT::apply_security_shield_for_securified_entity( + entity_applying_shield.clone(), + SecurityStructureOfFactorInstances::sample(), + RolesExercisableInTransactionManifestCombination::InitiateWithPrimaryCompleteWithConfirmation, + ).unwrap(); + + let expected_manifest_str = + fixture_rtm!("update_shield_of_account_init_with_P_confirm_with_C"); + manifest_eq(manifest.clone(), expected_manifest_str); + assert!(expected_manifest_str.contains("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g")); + + let manifest = SUT::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_securified_account_paid_by_account(entity_applying_shield.clone(), entity_applying_shield.clone(), manifest.clone(), Decimal192::ten()).unwrap(); + + let expected_manifest_str = + fixture_rtm!("update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield"); + manifest_eq(manifest.clone(), expected_manifest_str); + + let manifest = SUT::modify_manifest_add_lock_fee_against_xrd_vault_of_access_controller(manifest, Decimal192::nine(), entity_applying_shield); + + let expected_manifest_str = + fixture_rtm!("update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield_with_xrd_lock"); + manifest_eq(manifest, expected_manifest_str); + } + + fn test_update_shield_of_securified_persona<'a>( + roles: RolesExercisableInTransactionManifestCombination, + rtm: impl Fn() -> &'a str, + ) -> Vec { + let entity_applying_shield = SecurifiedPersona::sample(); + let instances = SecurityStructureOfFactorInstances::sample_other(); + + let manifest = SUT::apply_security_shield_for_securified_entity( + entity_applying_shield.clone(), + instances, + roles, + ) + .unwrap(); + let expected_manifest_str = rtm(); + manifest_eq(manifest.clone(), expected_manifest_str); + manifest + .instructions() + .iter() + .map(|i| i.get_discriminator()) + .collect_vec() + } + + #[test] + fn update_shield_of_securified_persona_init_with_R_confirm_with_P() { + let instruction_discriminants = test_update_shield_of_securified_persona( + RolesExercisableInTransactionManifestCombination::InitiateWithRecoveryCompleteWithPrimary, + || fixture_rtm!("update_shield_of_persona_init_with_R_confirm_with_P") + ); + assert_eq!( + instruction_discriminants, + vec![ + CallMethod::ID, // init + CallMethod::ID, // quick confirm + CallMetadataMethod::ID, // set ROLA key + ] + ); + } + + #[test] + fn update_shield_of_securified_persona_init_with_P_confirm_with_C() { + let instruction_discriminants = test_update_shield_of_securified_persona( + RolesExercisableInTransactionManifestCombination::InitiateWithPrimaryCompleteWithConfirmation, + || fixture_rtm!("update_shield_of_persona_init_with_P_confirm_with_C") + ); + assert_eq!( + instruction_discriminants, + vec![ + CallMetadataMethod::ID, // set ROLA key + CallMethod::ID, // init + CallMethod::ID, // quick confirm + ], + "Expected to FIRST set ROLA key and THEN init - since we can set it using existing factors." + ); + } + + #[test] + fn update_shield_of_securified_persona_init_with_P_confirm_with_T() { + let instruction_discriminants = test_update_shield_of_securified_persona( + RolesExercisableInTransactionManifestCombination::InitiateWithPrimaryDelayedCompletion, + || fixture_rtm!("update_shield_of_persona_init_with_P_confirm_with_T") + ); + assert_eq!( + instruction_discriminants, + vec![ + CallMethod::ID // init + ], + ); + } + + #[test] + fn update_shield_of_securified_persona_init_with_R_confirm_with_C() { + let instruction_discriminants = test_update_shield_of_securified_persona( + RolesExercisableInTransactionManifestCombination::InitiateWithRecoveryCompleteWithConfirmation, + || fixture_rtm!("update_shield_of_persona_init_with_R_confirm_with_C") + ); + assert_eq!( + instruction_discriminants, + vec![ + CallMethod::ID, // init + CallMethod::ID, // quick confirm + CallMetadataMethod::ID, // set ROLA key + ] + ); + } + + #[test] + fn update_shield_of_securified_persona_init_with_R_confirm_with_T() { + let instruction_discriminants = test_update_shield_of_securified_persona( + RolesExercisableInTransactionManifestCombination::InitiateWithRecoveryDelayedCompletion, + || fixture_rtm!("update_shield_of_persona_init_with_R_confirm_with_T") + ); + assert_eq!( + instruction_discriminants, + vec![CallMethod::ID], + "init with R complete with T should not set rola key - since we cannot" + ); + } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/manifests_security_shield.rs b/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_unsecurified_entity.rs similarity index 65% rename from crates/transaction/manifests/src/manifests_security_shield/manifests_security_shield.rs rename to crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_unsecurified_entity.rs index 43d797ccf..a0ce8c950 100644 --- a/crates/transaction/manifests/src/manifests_security_shield/manifests_security_shield.rs +++ b/crates/transaction/manifests/src/manifests_security_shield/manifests_securify_shield_unsecurified_entity.rs @@ -1,110 +1,44 @@ use profile_supporting_types::AnyUnsecurifiedEntity; use radix_common::prelude::ACCESS_CONTROLLER_PACKAGE as SCRYPTO_ACCESS_CONTROLLER_PACKAGE; -use radix_engine_interface::blueprints::{ - access_controller::{ - AccessControllerCreateManifestInput as ScryptoAccessControllerCreateManifestInput, - ACCESS_CONTROLLER_BLUEPRINT as SCRYPTO_ACCESS_CONTROLLER_BLUEPRINT, - ACCESS_CONTROLLER_CREATE_IDENT as SCRYPTO_ACCESS_CONTROLLER_CREATE_IDENT, - }, - account::AccountSecurifyManifestInput as ScryptoAccountSecurifyManifestInput, +use radix_engine_interface::blueprints::access_controller::{ + AccessControllerCreateManifestInput as ScryptoAccessControllerCreateManifestInput, + ACCESS_CONTROLLER_BLUEPRINT as SCRYPTO_ACCESS_CONTROLLER_BLUEPRINT, + ACCESS_CONTROLLER_CREATE_IDENT as SCRYPTO_ACCESS_CONTROLLER_CREATE_IDENT, }; -use radix_transactions::prelude::ManifestBuilder; use crate::prelude::*; -#[derive(Debug, Clone)] -pub struct TransactionManifestApplySecurityShieldUnsecurifiedInput { - pub security_structure_of_factor_instances: - SecurityStructureOfFactorInstances, -} - -impl TransactionManifestApplySecurityShieldUnsecurifiedInput { - pub fn new( - security_structure_of_factor_instances: - SecurityStructureOfFactorInstances, - ) -> Self { - Self { - security_structure_of_factor_instances, - } - } -} - -pub trait TransactionManifestSecurifyEntity: Sized { +pub trait TransactionManifestSecurifyUnsecurifiedEntity: + Sized + TransactionManifestSetRolaKey +{ fn apply_security_shield_for_unsecurified_entity( unsecurified_entity: AnyUnsecurifiedEntity, - input: TransactionManifestApplySecurityShieldUnsecurifiedInput, + security_structure_of_factor_instances: + SecurityStructureOfFactorInstances, ) -> Result; - - fn set_rola_key( - builder: ManifestBuilder, - authentication_signing_factor_instance: &HierarchicalDeterministicFactorInstance, - entity_address: &AddressOfAccountOrPersona, - ) -> ManifestBuilder; } -impl TransactionManifestSecurifyEntity for TransactionManifest { - fn set_rola_key( - builder: ManifestBuilder, - authentication_signing_factor_instance: - &HierarchicalDeterministicFactorInstance, - entity_address: &AddressOfAccountOrPersona, - ) -> ManifestBuilder { - let rola_key_hash = PublicKeyHash::hash( - authentication_signing_factor_instance.public_key(), - ); - let owner_key_hashes = vec![rola_key_hash]; - Self::set_owner_keys_hashes_on_builder( - entity_address, - owner_key_hashes, - builder, - ) - } - +impl TransactionManifestSecurifyUnsecurifiedEntity for TransactionManifest { /// We do NOT top of XRD vault of AccessController - yet! /// Host will need to call the function: - /// `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account` + /// `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account` /// after user has selected account to pay in wallet GUI. /// (and as usual also call `modify_manifest_lock_fee`) fn apply_security_shield_for_unsecurified_entity( unsecurified_entity: AnyUnsecurifiedEntity, - input: TransactionManifestApplySecurityShieldUnsecurifiedInput, + security_structure_of_factor_instances: + SecurityStructureOfFactorInstances, ) -> Result { let entity_address = unsecurified_entity.address(); - let TransactionManifestApplySecurityShieldUnsecurifiedInput { - security_structure_of_factor_instances, - } = input.clone(); security_structure_of_factor_instances .assert_has_entity_kind(entity_address.get_entity_kind())?; - let (security_entity_identifier, owner_badge) = - if entity_address.is_identity() { - ( - SCRYPTO_IDENTITY_SECURIFY_IDENT, - SCRYPTO_IDENTITY_OWNER_BADGE, - ) - } else { - (SCRYPTO_ACCOUNT_SECURIFY_IDENT, SCRYPTO_ACCOUNT_OWNER_BADGE) - }; - - let mut builder = ScryptoTransactionManifestBuilder::new(); - // Securify the entity which will return an entity owner badge onto the worktop. - let owner_badge_bucket_name = "owner_badge_bucket"; - { - builder = builder.call_method( - &entity_address, - security_entity_identifier, - ScryptoAccountSecurifyManifestInput {}, - ); - - // Create a bucket out of the entity owner badge. - builder = builder.take_from_worktop( - owner_badge, - 1, - owner_badge_bucket_name, - ); - }; + let (mut builder, owner_badge_bucket) = Self::put_owner_badge_in_bucket( + ScryptoTransactionManifestBuilder::new(), + &unsecurified_entity, + ); // Create an access controller for the entity. builder = { @@ -131,8 +65,6 @@ impl TransactionManifestSecurifyEntity for TransactionManifest { .clone(), ); - let owner_badge_bucket = builder.bucket(owner_badge_bucket_name); - builder.call_function( SCRYPTO_ACCESS_CONTROLLER_PACKAGE, SCRYPTO_ACCESS_CONTROLLER_BLUEPRINT, @@ -166,7 +98,7 @@ impl TransactionManifestSecurifyEntity for TransactionManifest { // N.B. // We do NOT top of XRD vault of AccessController - yet! // Host will need to call the function: - // `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account` + // `modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account` // after user has selected account to pay in wallet GUI. // (and as usual also call `modify_manifest_lock_fee`) @@ -185,16 +117,14 @@ mod tests { fn test_securify_unsecurified_account() { let expected_manifest_str = fixture_rtm!("create_access_controller_for_account"); - let entity = Account::sample(); + let account = Account::sample(); let security_structure_of_factor_instances = SecurityStructureOfFactorInstances::sample(); let manifest = TransactionManifest::apply_security_shield_for_unsecurified_entity( - AnyUnsecurifiedEntity::new(entity.clone().into()).unwrap(), - TransactionManifestApplySecurityShieldUnsecurifiedInput::new( - security_structure_of_factor_instances.clone(), - ), + AnyUnsecurifiedEntity::new(account.clone()).unwrap(), + security_structure_of_factor_instances.clone(), ) .unwrap(); manifest_eq(manifest.clone(), expected_manifest_str); @@ -214,13 +144,13 @@ mod tests { .contains(&PublicKeyHash::hash(fi.public_key()).to_string())); } - assert!(expected_manifest_str.contains(&entity.address.to_string())); + assert!(expected_manifest_str.contains(&account.address.to_string())); let bob = Account::sample_bob(); - let with_ac_xrd_vault_top_up_by_unsecurified_account = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( + let with_ac_xrd_vault_top_up_by_unsecurified_account = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account( bob.clone(), - entity.clone(), + AnyUnsecurifiedEntity::new( account.clone()).unwrap(), manifest.clone(), None, ); @@ -246,9 +176,9 @@ mod tests { }, ); - let with_ac_xrd_vault_top_up_by_securified_account_amount_42 = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( + let with_ac_xrd_vault_top_up_by_securified_account_amount_42 = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account( grace_secure.clone(), - entity.clone(), + AnyUnsecurifiedEntity::new(account.clone()).unwrap(), manifest.clone(), Decimal192::from(42), ); @@ -266,20 +196,17 @@ mod tests { fn test_securify_unsecurified_persona() { let expected_manifest_str = fixture_rtm!("create_access_controller_for_persona"); - let entity = Persona::sample_other(); + let persona = Persona::sample_other(); let security_structure_of_factor_instances = SecurityStructureOfFactorInstances::sample_other(); let manifest = TransactionManifest::apply_security_shield_for_unsecurified_entity( - AnyUnsecurifiedEntity::new(entity.clone().into()).unwrap(), - TransactionManifestApplySecurityShieldUnsecurifiedInput::new( - security_structure_of_factor_instances.clone(), - ), + AnyUnsecurifiedEntity::new(persona.clone()).unwrap(), + security_structure_of_factor_instances.clone(), ) .unwrap(); - manifest_eq(manifest, expected_manifest_str); - + manifest_eq(manifest.clone(), expected_manifest_str); assert!(expected_manifest_str.contains("securify")); assert!(expected_manifest_str.contains( &security_structure_of_factor_instances @@ -296,18 +223,60 @@ mod tests { .contains(&PublicKeyHash::hash(fi.public_key()).to_string())); } - assert!(expected_manifest_str.contains(&entity.address.to_string())); + assert!(expected_manifest_str.contains(&persona.address.to_string())); + + let bob = Account::sample_bob(); + + let with_ac_xrd_vault_top_up_by_unsecurified_account = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account( + bob.clone(), + AnyUnsecurifiedEntity::new(persona.clone()).unwrap(), + manifest.clone(), + None, + ); + + let expected_manifest_str = + fixture_rtm!("create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_unsecurified_account"); + + manifest_eq( + with_ac_xrd_vault_top_up_by_unsecurified_account, + expected_manifest_str, + ); + + let grace_secure = Account::sample_securified_mainnet( + "Grace", + 6, + HierarchicalDeterministicFactorInstance::sample_mainnet_account_device_factor_fs_10_unsecurified_at_index(0), + || { + GeneralRoleWithHierarchicalDeterministicFactorInstances::r6( + HierarchicalDeterministicFactorInstance::sample_id_to_instance( + CAP26EntityKind::Account, + Hardened::from_local_key_space(6u32, IsSecurified(true)).unwrap(), + )) + }, + ); + + let with_ac_xrd_vault_top_up_by_securified_account_amount_42 = TransactionManifest::modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account( + grace_secure.clone(), + AnyUnsecurifiedEntity::new( persona.clone()).unwrap(), + manifest.clone(), + Decimal192::from(42), + ); + + let expected_manifest_str = + fixture_rtm!("create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_securified_account_amount_42"); + + manifest_eq( + with_ac_xrd_vault_top_up_by_securified_account_amount_42, + expected_manifest_str, + ); } #[test] fn test_mismatch_entity_kind_account_persona() { let manifest = TransactionManifest::apply_security_shield_for_unsecurified_entity( - AnyUnsecurifiedEntity::new(Account::sample_other().into()) - .unwrap(), - TransactionManifestApplySecurityShieldUnsecurifiedInput::new( - SecurityStructureOfFactorInstances::sample_other(), - ), + AnyUnsecurifiedEntity::new(Account::sample_other()).unwrap(), + SecurityStructureOfFactorInstances::sample_other(), ); assert_eq!(manifest, Err(CommonError::SecurityStructureOfFactorInstancesEntityDiscrepancyInEntityKind { entity_kind_of_entity: CAP26EntityKind::Account.to_string(), entity_kind_of_factor_instances: CAP26EntityKind::Identity.to_string() })); } @@ -316,11 +285,8 @@ mod tests { fn test_mismatch_entity_kind_persona_account() { let manifest = TransactionManifest::apply_security_shield_for_unsecurified_entity( - AnyUnsecurifiedEntity::new(Persona::sample_other().into()) - .unwrap(), - TransactionManifestApplySecurityShieldUnsecurifiedInput::new( - SecurityStructureOfFactorInstances::sample(), - ), + AnyUnsecurifiedEntity::new(Persona::sample_other()).unwrap(), + SecurityStructureOfFactorInstances::sample(), ); assert_eq!(manifest, Err(CommonError::SecurityStructureOfFactorInstancesEntityDiscrepancyInEntityKind { entity_kind_of_entity: CAP26EntityKind::Identity.to_string(), entity_kind_of_factor_instances: CAP26EntityKind::Account.to_string() })); } diff --git a/crates/transaction/manifests/src/manifests_security_shield/mod.rs b/crates/transaction/manifests/src/manifests_security_shield/mod.rs index 8e47aa265..6ba5ebe5a 100644 --- a/crates/transaction/manifests/src/manifests_security_shield/mod.rs +++ b/crates/transaction/manifests/src/manifests_security_shield/mod.rs @@ -1,6 +1,19 @@ -#[allow(clippy::module_inception)] -mod manifests_security_shield; +mod access_controller_factors_and_time_input; +mod confirm_timed_recovery; +mod lock_fee_against_xrd_vault_of_access_controller; +mod manifests_securify_shield_securified_entity; +mod manifests_securify_shield_unsecurified_entity; +mod roles_exercisable_in_transaction_manifest_combination; +mod set_rola_key; mod top_up_access_controller_xrd_vault; +mod transaction_manifest_unsecurified_entity_owner_badge_into_bucket_putting; -pub use manifests_security_shield::*; +pub use access_controller_factors_and_time_input::*; +pub use confirm_timed_recovery::*; +pub use lock_fee_against_xrd_vault_of_access_controller::*; +pub use manifests_securify_shield_securified_entity::*; +pub use manifests_securify_shield_unsecurified_entity::*; +pub use set_rola_key::*; pub use top_up_access_controller_xrd_vault::*; +pub use roles_exercisable_in_transaction_manifest_combination::*; +pub use transaction_manifest_unsecurified_entity_owner_badge_into_bucket_putting::*; diff --git a/crates/transaction/manifests/src/manifests_security_shield/roles_exercisable_in_transaction_manifest_combination.rs b/crates/transaction/manifests/src/manifests_security_shield/roles_exercisable_in_transaction_manifest_combination.rs new file mode 100644 index 000000000..b3d76c3f0 --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/roles_exercisable_in_transaction_manifest_combination.rs @@ -0,0 +1,262 @@ +use crate::prelude::*; + +use enum_as_inner::EnumAsInner; +use profile_supporting_types::AnySecurifiedEntity; +use radix_common::prelude::{ + ManifestEncode as ScryptoManifestEncode, + ManifestSborTuple as ScryptoManifestSborTuple, +}; +use radix_engine_interface::blueprints::access_controller::{ + AccessControllerInitiateRecoveryAsPrimaryInput as ScryptoAccessControllerInitiateRecoveryAsPrimaryInput, + AccessControllerInitiateRecoveryAsRecoveryInput as ScryptoAccessControllerInitiateRecoveryAsRecoveryInput, + AccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput as ScryptoAccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput, + AccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput as ScryptoAccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput, + ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_PRIMARY_IDENT as SCRYPTO_ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_PRIMARY_IDENT, + ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_RECOVERY_IDENT as SCRYPTO_ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_RECOVERY_IDENT, + ACCESS_CONTROLLER_QUICK_CONFIRM_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT as SCRYPTO_ACCESS_CONTROLLER_QUICK_CONFIRM_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT, + ACCESS_CONTROLLER_QUICK_CONFIRM_RECOVERY_ROLE_RECOVERY_PROPOSAL_IDENT as SCRYPTO_ACCESS_CONTROLLER_QUICK_CONFIRM_RECOVERY_ROLE_RECOVERY_PROPOSAL_IDENT, +}; + +/// A "selector" of which combination of Roles we can exercise with used +/// to build different flavours of TransactionManifest for the Security Shield +/// update. +/// +/// Each combination of roles allows us to skip signing with certain factors +/// and still be able to recover + confirm the AccessController update. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, enum_iterator::Sequence)] +pub enum RolesExercisableInTransactionManifestCombination { + /// Initiates recovery using `Recovery` role and quick confirms using + /// `Primary` role explicitly. + InitiateWithRecoveryCompleteWithPrimary, + + /// Initiates recovery using `Recovery` role and quick confirms using + /// `Confirmation` role explicitly. + InitiateWithRecoveryCompleteWithConfirmation, + + /// Initiate recovery with `Recovery` role and use timed confirmation. + /// + /// Since this roles combination does not explicitly use the Confirmation + /// Role we will not include any confirm Instruction in the manifest + /// we build for this kind. Instead, if this is the TransactionManifest which + /// we will be submitting to the network, the host (user) will need to wait + /// until the transaction is confirmed and then update Profile to keep + /// track of the fact that the entity is in between states of recovery. + /// TODO: TBD probably a new variant of the `ProvisionalSecurifiedConfig` + /// `WaitingForTimedRecovery(SecurityStructureOfFactorInstances)` or similar. + /// + /// Host will also need to schedule a notification for user so that host + /// can call the `confirm_timed_recovery` method after the time has elapsed. + InitiateWithRecoveryDelayedCompletion, + + /// Initiates recovery using `Primary` role and quick confirms using + /// `Confirmation` role explicitly. + InitiateWithPrimaryCompleteWithConfirmation, + + /// ‼️ Requires future network upgrade "Dugong" + /// + /// Initiate recovery with `Primary` role and use timed confirmation. + /// + /// Since this roles combination does not explicitly use the Confirmation + /// Role we will not include any confirm Instruction in the manifest + /// we build for this kind. Instead, if this is the TransactionManifest which + /// we will be submitting to the network, the host (user) will need to wait + /// until the transaction is confirmed and then update Profile to keep + /// track of the fact that the entity is in between states of recovery. + /// TODO: TBD probably a new variant of the `ProvisionalSecurifiedConfig` + /// `WaitingForTimedRecovery(SecurityStructureOfFactorInstances)` or similar. + /// + /// Host will also need to schedule a notification for user so that host + /// can call the `confirm_timed_recovery` method after the time has elapsed. + /// + /// ‼️ Requires future network upgrade "Dugong" + InitiateWithPrimaryDelayedCompletion, + // TODO: + // FUTURE IMPROVEMENTS, + // User can't initiate themselves and needs to send a request to an external source (e.g. a friend or custodian) + // ExternalInitiateWithPrimary + // ExternalInitiateWithRecovery +} + +pub trait CallMethodInput: + ScryptoManifestEncode + ScryptoManifestSborTuple +{ +} +impl CallMethodInput + for T +{ +} + +/// Depending on the role used to initiate recovery, and if we are quick confirming +/// the recovery proposal we need to either place SET_METADATA instruction which +/// updates the ROLA key with the new factors before the recovery proposal - requiring +/// the OLD PrimaryRole factors to auth the transaction - or we can quick confirm +/// we will place the SET_METADATA instruction after we have (quick) confirmed the +/// recovery proposal. +#[derive(Clone, Debug, PartialEq, Eq, EnumAsInner)] +pub enum OrderOfInstructionSettingRolaKey { + /// Place SET_METADATA instruction before initiating recovery - so that + /// we can auth with the OLD factors of Primary role. + BeforeInitRecovery, + /// Place SET_METADATA instruction after quick confirming the recovery proposal + /// => requiring us to auth with the NEW factors of Primary role. + AfterQuickConfirm, + + /// No need to set ROLA key + NotNeeded, + + /// Cannot set ROLA key in this TX - must do it in a future TX when we confirm recovery + MustSetInFutureTxForConfirmRecovery, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +enum RoleInitiatingRecovery { + Primary, + Recovery, +} + +impl RolesExercisableInTransactionManifestCombination { + pub fn manifest_end_user_gets_to_preview() -> Self { + Self::InitiateWithRecoveryCompleteWithConfirmation + } + + pub fn all() -> IndexSet { + enum_iterator::all::().collect() + } + + pub fn order_of_instruction_setting_rola( + &self, + security_structure_of_factor_instances: &SecurityStructureOfFactorInstances, + entity: &AnySecurifiedEntity, + ) -> OrderOfInstructionSettingRolaKey { + if security_structure_of_factor_instances + .authentication_signing_factor_instance + == entity.current_authentication_signing_factor_instance() + { + // The factor of ROLA key is the same as the current factor of the entity + // => we can skip setting the ROLA key. + return OrderOfInstructionSettingRolaKey::NotNeeded; + } + + if !self.can_quick_confirm() { + // N.B. + // In case of role initiating the recovery being `Primary` we CAN in fact + // set the ROLA key in the same transaction as we initiate recovery, however, + // if we CANCEL the recovery proposal (instead of CONFIRM) in the future + // transaction we would be in a bad state (not using the old nor the new shield). + return OrderOfInstructionSettingRolaKey::MustSetInFutureTxForConfirmRecovery; + } + + match self.role_initiating_recovery() { + RoleInitiatingRecovery::Primary => { + // We can exercise the Primary Role => no need + // to set the ROLA key after recovery and use new factors, instead + // we can use existing factors + OrderOfInstructionSettingRolaKey::BeforeInitRecovery + } + RoleInitiatingRecovery::Recovery => { + // we can quick confirm so we can always set the ROLA key using + // the NEW factors - disregarding of which role initiated recovery. + OrderOfInstructionSettingRolaKey::AfterQuickConfirm + } + } + } + + fn role_initiating_recovery(&self) -> RoleInitiatingRecovery { + match self { + Self::InitiateWithPrimaryCompleteWithConfirmation + | Self::InitiateWithPrimaryDelayedCompletion => { + RoleInitiatingRecovery::Primary + } + Self::InitiateWithRecoveryCompleteWithPrimary + | Self::InitiateWithRecoveryCompleteWithConfirmation + | Self::InitiateWithRecoveryDelayedCompletion => { + RoleInitiatingRecovery::Recovery + } + } + } + + fn can_quick_confirm(&self) -> bool { + match self { + Self::InitiateWithPrimaryCompleteWithConfirmation + | Self::InitiateWithRecoveryCompleteWithConfirmation + | Self::InitiateWithRecoveryCompleteWithPrimary => true, + Self::InitiateWithRecoveryDelayedCompletion + | Self::InitiateWithPrimaryDelayedCompletion => false, + } + } + + /// Returns method identifier and input for **initiating** recovery + /// on an AccessController - depending on which roles we can exercise. + pub fn input_for_initialization( + &self, + factors_and_time: &AccessControllerFactorsAndTimeInput, + ) -> (&'static str, Box) { + match self.role_initiating_recovery() { + RoleInitiatingRecovery::Primary => { + ( + SCRYPTO_ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_PRIMARY_IDENT, + Box::new( + ScryptoAccessControllerInitiateRecoveryAsPrimaryInput::from( + factors_and_time, + ), + ), + ) + } + RoleInitiatingRecovery::Recovery => { + ( + SCRYPTO_ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_RECOVERY_IDENT, + Box::new( + ScryptoAccessControllerInitiateRecoveryAsRecoveryInput::from( + factors_and_time, + ), + ), + ) + } + } + } + + /// Returns method identifier and input for **confirm** recovery + /// on an AccessController - depending on which roles we can exercise. + /// + /// **MUST** use the analogous method which was used to initiate recovery. + pub fn input_for_quick_confirm( + &self, + factors_and_time: &AccessControllerFactorsAndTimeInput, + ) -> Option<(&'static str, Box)> { + if self.can_quick_confirm() { + match self.role_initiating_recovery() { + RoleInitiatingRecovery::Primary => Some(( + SCRYPTO_ACCESS_CONTROLLER_QUICK_CONFIRM_PRIMARY_ROLE_RECOVERY_PROPOSAL_IDENT, + Box::new(ScryptoAccessControllerQuickConfirmPrimaryRoleRecoveryProposalInput::from(factors_and_time)) + )), + RoleInitiatingRecovery::Recovery => Some(( + SCRYPTO_ACCESS_CONTROLLER_QUICK_CONFIRM_RECOVERY_ROLE_RECOVERY_PROPOSAL_IDENT, + Box::new(ScryptoAccessControllerQuickConfirmRecoveryRoleRecoveryProposalInput::from(factors_and_time)) + )) + } + } else { + // Time based cannot happen yet - host (user) need to wait the specified + // amount of time (factors_and_time.time) before calling this method. + // So host will need to schedule a notification for user so that host + // can call this method after the time has elapsed. + None + } + } +} + +pub trait TransactionManifestExplicitlyReferencesPrimaryRole { + fn explicitly_references_primary_role(&self) -> bool; +} +impl TransactionManifestExplicitlyReferencesPrimaryRole + for TransactionManifest +{ + fn explicitly_references_primary_role(&self) -> bool { + let has = |identifier: &str| -> bool { + self.instructions() + .iter() + .any(|instruction| matches!(instruction, ScryptoInstruction::CallMethod(method) if method.method_name == identifier)) + }; + + has(SCRYPTO_ACCESS_CONTROLLER_INITIATE_RECOVERY_AS_PRIMARY_IDENT) + } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/set_rola_key.rs b/crates/transaction/manifests/src/manifests_security_shield/set_rola_key.rs new file mode 100644 index 000000000..bf96273c7 --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/set_rola_key.rs @@ -0,0 +1,30 @@ +use radix_transactions::prelude::ManifestBuilder; + +use crate::prelude::*; + +pub trait TransactionManifestSetRolaKey: Sized { + fn set_rola_key( + builder: ManifestBuilder, + authentication_signing_factor_instance: &HierarchicalDeterministicFactorInstance, + entity_address: &AddressOfAccountOrPersona, + ) -> ManifestBuilder; +} + +impl TransactionManifestSetRolaKey for TransactionManifest { + fn set_rola_key( + builder: ManifestBuilder, + authentication_signing_factor_instance: + &HierarchicalDeterministicFactorInstance, + entity_address: &AddressOfAccountOrPersona, + ) -> ManifestBuilder { + let rola_key_hash = PublicKeyHash::hash( + authentication_signing_factor_instance.public_key(), + ); + let owner_key_hashes = vec![rola_key_hash]; + Self::set_owner_keys_hashes_on_builder( + entity_address, + owner_key_hashes, + builder, + ) + } +} diff --git a/crates/transaction/manifests/src/manifests_security_shield/top_up_access_controller_xrd_vault.rs b/crates/transaction/manifests/src/manifests_security_shield/top_up_access_controller_xrd_vault.rs index d9943dba4..260a9dc90 100644 --- a/crates/transaction/manifests/src/manifests_security_shield/top_up_access_controller_xrd_vault.rs +++ b/crates/transaction/manifests/src/manifests_security_shield/top_up_access_controller_xrd_vault.rs @@ -1,3 +1,4 @@ +use profile_supporting_types::{AnySecurifiedEntity, AnyUnsecurifiedEntity}; use radix_common::prelude::ManifestGlobalAddress; use radix_engine_interface::blueprints::access_controller::{ AccessControllerContributeRecoveryFeeManifestInput, @@ -20,14 +21,10 @@ pub trait TransactionManifestAccessControllerXrdVaultToppingUp { /// at the end of `manifest` for topping the XRD vault of the access controller /// with `top_up_amount` many XRD. /// - /// N.B. We will call this method for both when `entity_applying_shield` is - /// securified or unsecurified. In the case of unsecurified entity we will use - /// the address reservation of `apply_security_shield_for_unsecurified_entity` + /// We will use the address reservation of `apply_security_shield_for_unsecurified_entity` /// (`ACCESS_CONTROLLER_ADDRESS_RESERVATION_NAME`) which we cannot access by id /// since Radix Engine discard those ids and uses internal ones, instead we need /// to use `ManifestGlobalAddress::Named(ScryptoManifestNamedAddress(0))`. - /// If `entity_applying_shield` is securified we will use the address of the - /// already existing access controller. /// /// If `payer` is securified we will also add a `create_proof` instruction for /// authenticating the withdrawal of XRD from the payer. @@ -36,14 +33,69 @@ pub trait TransactionManifestAccessControllerXrdVaultToppingUp { /// We allow to pass amount so that we can top of with more or less based on /// token balance of `payer` and current balance of the access controller (when /// we use this method for securified entities.) - fn modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( - payer: Account, - // TODO: remove `entity_applying_shield`, this should be read out from the manifest in a throwing function, `manifest.get_address_of_entity_applying_shield()` or similar which Omar need to provide us with, oh well we need the account here, so elsewhere, in SargonOS where we have access to Profile we would call `manifest.get_address_of_entity_applying_shield` and then lookup the entity. - entity_applying_shield: Account, + fn modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_unsecurified_account_paid_by_account( + payer: impl Into, + // TODO: remove `unsecurified_entity_applying_shield`, this should be read out from the manifest in a throwing function, `manifest.get_address_of_entity_applying_shield()` or similar which Omar need to provide us with, oh well we need the account here, so elsewhere, in SargonOS where we have access to Profile we would call `manifest.get_address_of_entity_applying_shield` and then lookup the entity. + unsecurified_entity_applying_shield: AnyUnsecurifiedEntity, manifest: TransactionManifest, top_up_amount: impl Into>, ) -> TransactionManifest { + assert!(!manifest.explicitly_references_primary_role(), "Unexpectedly classified manifest as updating of shield of securified entity, but it is not."); + Self::_modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( + payer, + unsecurified_entity_applying_shield.entity, + manifest, + top_up_amount, + ).expect("Should never fail") + } + + fn modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_of_securified_account_paid_by_account( + payer: impl Into, + // TODO: remove `securified_entity_applying_shield`, this should be read out from the manifest in a throwing function, `manifest.get_address_of_entity_applying_shield()` or similar which Omar need to provide us with, oh well we need the account here, so elsewhere, in SargonOS where we have access to Profile we would call `manifest.get_address_of_entity_applying_shield` and then lookup the entity. + securified_entity_applying_shield: impl Into, + manifest: TransactionManifest, + top_up_amount: impl Into>, + ) -> Result { + Self::_modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( + payer, + securified_entity_applying_shield.into().entity, + manifest, + top_up_amount, + ) + } + + fn _modify_manifest_add_withdraw_of_xrd_for_access_controller_xrd_vault_top_up_paid_by_account( + payer: impl Into, + // TODO: remove `entity_applying_shield`, this should be read out from the manifest in a throwing function, `manifest.get_address_of_entity_applying_shield()` or similar which Omar need to provide us with, oh well we need the account here, so elsewhere, in SargonOS where we have access to Profile we would call `manifest.get_address_of_entity_applying_shield` and then lookup the entity. + entity_applying_shield: AccountOrPersona, + manifest: TransactionManifest, + top_up_amount: impl Into>, + ) -> Result { + let payer = payer.into(); let address_of_paying_account = payer.address(); + + { + // Try to eagerly identify invalid manifest. + // We dont _need_ this and might remove it. + // but I think this will work. + + let payer_is_entity_applying_shield = + entity_applying_shield.address() == payer.address().into(); + if payer_is_entity_applying_shield { + let cannot_exercise_primary_role = + !manifest.explicitly_references_primary_role(); + let is_unable_to_top_up_xrd_vault = + payer_is_entity_applying_shield + && cannot_exercise_primary_role; + if is_unable_to_top_up_xrd_vault { + // The payer is the entity applying the shield, but the manifest is not classified as + // to be able to exercise the primary role. Thus we will not be able to + // top up the XRD vault of the access controller. + return Err(CommonError::Unknown); // TODO: Add error + } + } + } + let mut builder = ManifestBuilder::with_manifest(manifest); let address_of_access_controller_to_top_up = @@ -120,10 +172,12 @@ pub trait TransactionManifestAccessControllerXrdVaultToppingUp { }, ); - TransactionManifest::sargon_built( + let manifest = TransactionManifest::sargon_built( builder, address_of_paying_account.network_id(), - ) + ); + + Ok(manifest) } } diff --git a/crates/transaction/manifests/src/manifests_security_shield/transaction_manifest_unsecurified_entity_owner_badge_into_bucket_putting.rs b/crates/transaction/manifests/src/manifests_security_shield/transaction_manifest_unsecurified_entity_owner_badge_into_bucket_putting.rs new file mode 100644 index 000000000..ec957bc2a --- /dev/null +++ b/crates/transaction/manifests/src/manifests_security_shield/transaction_manifest_unsecurified_entity_owner_badge_into_bucket_putting.rs @@ -0,0 +1,58 @@ +use profile_supporting_types::AnyUnsecurifiedEntity; + +use crate::prelude::*; + +impl TransactionManifestUnsecurifiedEntityOwnerBadgeIntoBucketPutting + for TransactionManifest +{ +} + +pub trait TransactionManifestUnsecurifiedEntityOwnerBadgeIntoBucketPutting { + /// Produces and puts the owner badge of an Unsecurified Entity by calling + /// "securify" and put said owner badge in a Bucket and returns the bucket. + fn put_owner_badge_in_bucket( + builder: ScryptoTransactionManifestBuilder, + unsecurified_entity: &AnyUnsecurifiedEntity, + ) -> (ScryptoTransactionManifestBuilder, ScryptoManifestBucket) { + let owner_badge_bucket_name = "owner_badge_bucket"; + let owner_badge = match unsecurified_entity.entity.get_entity_kind() { + CAP26EntityKind::Account => SCRYPTO_ACCOUNT_OWNER_BADGE, + CAP26EntityKind::Identity => SCRYPTO_IDENTITY_OWNER_BADGE, + }; + let mut builder = Self::call_securify_for_unsecurified_entity( + builder, + unsecurified_entity, + ); + // Create a bucket out of the entity owner badge. + builder = + builder.take_from_worktop(owner_badge, 1, owner_badge_bucket_name); + + let owner_badge_bucket = builder.bucket(owner_badge_bucket_name); + + (builder, owner_badge_bucket) + } + + /// Calls "securify" for an unsecurified entity which places the owner badge + /// on the worktop. + fn call_securify_for_unsecurified_entity( + builder: ScryptoTransactionManifestBuilder, + unsecurified_entity: &AnyUnsecurifiedEntity, + ) -> ScryptoTransactionManifestBuilder { + let mut builder = builder; + + let is_account = unsecurified_entity.entity.is_account_entity(); + + let securify_entity_identifier = if is_account { + SCRYPTO_ACCOUNT_SECURIFY_IDENT + } else { + SCRYPTO_IDENTITY_SECURIFY_IDENT + }; + builder = builder.call_method( + unsecurified_entity.address().scrypto(), + securify_entity_identifier, + (), + ); + + builder + } +} diff --git a/crates/transaction/models/Cargo.toml b/crates/transaction/models/Cargo.toml index d751180e3..a843a6b66 100644 --- a/crates/transaction/models/Cargo.toml +++ b/crates/transaction/models/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "transaction-models" -version = "1.1.122" +version = "1.1.123" edition = "2021" diff --git a/crates/uniffi/conversion-macros/Cargo.toml b/crates/uniffi/conversion-macros/Cargo.toml index 05c145ef3..51b154d62 100644 --- a/crates/uniffi/conversion-macros/Cargo.toml +++ b/crates/uniffi/conversion-macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sargon-uniffi-conversion-macros" -version = "1.1.122" +version = "1.1.123" edition = "2021" [dependencies] diff --git a/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml b/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml index cd85e7385..a3831250c 100644 --- a/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml +++ b/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sargon-uniffi" -version = "1.1.122" +version = "1.1.123" edition = "2021" build = "build.rs" diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/matrices/decl_matrix_macro.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/matrices/decl_matrix_macro.rs index 23fdb97b0..643a58ced 100644 --- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/matrices/decl_matrix_macro.rs +++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/matrices/decl_matrix_macro.rs @@ -25,7 +25,7 @@ macro_rules! matrix_conversion { pub recovery_role: #recovery_role_type, pub confirmation_role: #confirmation_role_type, - pub number_of_days_until_auto_confirm: u16, + pub time_until_delayed_confirmation_is_callable: TimePeriod, } delegate_debug_into!(#struct_name, #internal_struct_name); @@ -36,8 +36,8 @@ macro_rules! matrix_conversion { primary_role: value.primary().clone().into(), recovery_role: value.recovery().clone().into(), confirmation_role: value.confirmation().clone().into(), - number_of_days_until_auto_confirm: value - .number_of_days_until_auto_confirm, + time_until_delayed_confirmation_is_callable: value + .time_until_delayed_confirmation_is_callable.into(), } } } @@ -49,7 +49,7 @@ macro_rules! matrix_conversion { self.primary_role.clone().into(), self.recovery_role.clone().into(), self.confirmation_role.clone().into(), - self.number_of_days_until_auto_confirm, + self.time_until_delayed_confirmation_is_callable.into(), ) } } diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period.rs index 2a249fb4d..606b74e3f 100644 --- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period.rs +++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period.rs @@ -4,7 +4,9 @@ use sargon::TimePeriod as InternalTimePeriod; /// Time period unit expressed in days, weeks, or years. /// /// Used to represent in the hosts UI the time period. -#[derive(Clone, PartialEq, Eq, Hash, InternalConversion, uniffi::Record)] +#[derive( + Clone, Debug, Copy, PartialEq, Eq, Hash, InternalConversion, uniffi::Record, +)] pub struct TimePeriod { /// The value of the time period. pub value: u16, diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs index 8a1e0cc7b..73726cbae 100644 --- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs +++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs @@ -102,9 +102,11 @@ impl SecurityShieldBuilder { .collect() } - pub fn get_time_period_until_auto_confirm(&self) -> TimePeriod { - self.get(|builder| builder.get_time_period_until_auto_confirm()) - .into() + pub fn get_time_until_timed_confirmation_is_callable(&self) -> TimePeriod { + self.get(|builder| { + builder.get_time_until_timed_confirmation_is_callable() + }) + .into() } pub fn get_name(&self) -> String { @@ -206,13 +208,14 @@ impl SecurityShieldBuilder { self.set(|builder| builder.set_threshold(threshold.into())) } - pub fn set_time_period_until_auto_confirm( + pub fn set_time_until_delayed_confirmation_is_callable( self: Arc, time_period: TimePeriod, ) -> Arc { self.set(|builder| { - builder - .set_time_period_until_auto_confirm(time_period.clone().into()) + builder.set_time_until_delayed_confirmation_is_callable( + time_period.into(), + ) }) } @@ -637,16 +640,16 @@ mod tests { assert_eq!( time_period_to_days( - &sut.clone().get_time_period_until_auto_confirm() + &sut.clone().get_time_until_timed_confirmation_is_callable() ), 14 ); - sut = sut.set_time_period_until_auto_confirm( + sut = sut.set_time_until_delayed_confirmation_is_callable( new_time_period_with_days(u16::MAX), ); assert_eq!( time_period_to_days( - &sut.clone().get_time_period_until_auto_confirm() + &sut.clone().get_time_until_timed_confirmation_is_callable() ), u16::MAX ); @@ -964,12 +967,15 @@ mod tests { FactorSource::sample_ledger_other(), ]; let name = "Auto Built"; - let days_to_auto_confirm = 237; + let days_until_timed_confirmation = TimePeriod { + value: 237, + unit: TimePeriodUnit::Days, + }; sut = sut .set_name(name.to_owned()) - .set_time_period_until_auto_confirm(new_time_period_with_days( - days_to_auto_confirm, - )) + .set_time_until_delayed_confirmation_is_callable( + new_time_period_with_days(237), + ) .add_factor_source_to_primary_threshold( FactorSource::sample_device_babylon().id(), ) @@ -986,8 +992,8 @@ mod tests { assert_eq!(shield.metadata.display_name.value, name.to_owned()); let matrix = shield.matrix_of_factors; assert_eq!( - matrix.number_of_days_until_auto_confirm, - days_to_auto_confirm + matrix.time_until_delayed_confirmation_is_callable, + days_until_timed_confirmation ); pretty_assertions::assert_eq!( diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs index 6fddd6ad2..63b157791 100644 --- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs +++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs @@ -14,8 +14,8 @@ pub enum SecurityShieldBuilderRuleViolation { #[error("Shield name is invalid")] ShieldNameInvalid, - #[error("The number of days until auto confirm must be greater than zero")] - NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero, + #[error("The number of days until timed confirm is callable must be greater than zero")] + NumberOfDaysUntilTimeBasedConfirmationMustBeGreaterThanZero, #[error("Recovery and confirmation factors overlap. No factor may be used in both the recovery and confirmation roles")] RecoveryAndConfirmationFactorsOverlap, diff --git a/fixtures/vector/deep_link_request_params.json b/fixtures/models/interaction/deep_link_request_params.json similarity index 100% rename from fixtures/vector/deep_link_request_params.json rename to fixtures/models/interaction/deep_link_request_params.json diff --git a/fixtures/vector/rola_challenge_payload_hash_vectors.json b/fixtures/models/interaction/rola_challenge_payload_hash_vectors.json similarity index 100% rename from fixtures/vector/rola_challenge_payload_hash_vectors.json rename to fixtures/models/interaction/rola_challenge_payload_hash_vectors.json diff --git a/fixtures/models/interaction/wallet_interaction_batch_of_transactions.json b/fixtures/models/interaction/wallet_interaction_batch_of_transactions.json new file mode 100644 index 000000000..83fa2ae9f --- /dev/null +++ b/fixtures/models/interaction/wallet_interaction_batch_of_transactions.json @@ -0,0 +1,20 @@ +{ + "transactions": [ + { + "transactionManifest": "CALL_METHOD\n Address(\"account_rdx128mh2ae9dsrwa0t8l37ayjrxxf0p84e6qm227ytxtcu447f5uw5m8w\")\n \"securify\"\n;\nTAKE_FROM_WORKTOP\n Address(\"resource_rdx1nfxxxxxxxxxxaccwnrxxxxxxxxx006664022062xxxxxxxxxaccwnr\")\n Decimal(\"1\")\n Bucket(\"bucket1\")\n;\nALLOCATE_GLOBAL_ADDRESS\n Address(\"package_rdx1pkgxxxxxxxxxcntrlrxxxxxxxxx000648572295xxxxxxxxxcntrlr\")\n \"AccessController\"\n AddressReservation(\"reservation1\")\n NamedAddress(\"address1\")\n;\nCREATE_ACCESS_CONTROLLER\n Bucket(\"bucket1\")\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0e8695a4117774464ca04bb6d10ce0b11aede12bd797dcdee811067094]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0e8695a4117774464ca04bb6d10ce0b11aede12bd797dcdee811067094]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0e8695a4117774464ca04bb6d10ce0b11aede12bd797dcdee811067094]\")\n )\n )\n )\n )\n )\n )\n )\n )\n Enum<1u8>(\n 20160u32\n )\n Enum<1u8>(\n AddressReservation(\"reservation1\")\n )\n;\nSET_METADATA\n Address(\"account_rdx128mh2ae9dsrwa0t8l37ayjrxxf0p84e6qm227ytxtcu447f5uw5m8w\")\n \"owner_keys\"\n Enum<143u8>(\n Array(\n Enum<1u8>(\n Bytes(\"8e7da995687de79d87a51e4acadccbeea15df2b165800247930298bc16\")\n )\n )\n )\n;\n", + "blobs": [] + }, + { + "transactionManifest": "CALL_METHOD\n Address(\"identity_rdx122kkqj7pc04gwsgcwsxmfmknlsg4qpz52rrs6vj72cujks4ukw993v\")\n \"securify\"\n;\nTAKE_FROM_WORKTOP\n Address(\"resource_rdx1nfxxxxxxxxxxdntwnrxxxxxxxxx002876444928xxxxxxxxxdntwnr\")\n Decimal(\"1\")\n Bucket(\"bucket1\")\n;\nALLOCATE_GLOBAL_ADDRESS\n Address(\"package_rdx1pkgxxxxxxxxxcntrlrxxxxxxxxx000648572295xxxxxxxxxcntrlr\")\n \"AccessController\"\n AddressReservation(\"reservation1\")\n NamedAddress(\"address1\")\n;\nCREATE_ACCESS_CONTROLLER\n Bucket(\"bucket1\")\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b5896b1b5a1de8573b3a90216e7b14b42aa11746ad2e0bcb0741c216d]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b5896b1b5a1de8573b3a90216e7b14b42aa11746ad2e0bcb0741c216d]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b5896b1b5a1de8573b3a90216e7b14b42aa11746ad2e0bcb0741c216d]\")\n )\n )\n )\n )\n )\n )\n )\n )\n Enum<1u8>(\n 20160u32\n )\n Enum<1u8>(\n AddressReservation(\"reservation1\")\n )\n;\nSET_METADATA\n Address(\"identity_rdx122kkqj7pc04gwsgcwsxmfmknlsg4qpz52rrs6vj72cujks4ukw993v\")\n \"owner_keys\"\n Enum<143u8>(\n Array(\n Enum<1u8>(\n Bytes(\"a9a3197f2553f4cfe4603e77fd1802f14490862e11a33d81c98c430e31\")\n )\n )\n )\n;\n", + "blobs": [] + }, + { + "transactionManifest": "CALL_METHOD\n Address(\"accesscontroller_rdx1c0duj4lq0dc3cpl8qd420fpn5eckh8ljeysvjm894lyl5ja5yq6y5a\")\n \"initiate_recovery_as_recovery\"\n Tuple(\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n )\n ),\n Enum<1u8>(\n 20160u32\n )\n )\n;\nCALL_METHOD\n Address(\"accesscontroller_rdx1c0duj4lq0dc3cpl8qd420fpn5eckh8ljeysvjm894lyl5ja5yq6y5a\")\n \"quick_confirm_recovery_role_recovery_proposal\"\n Tuple(\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[bfcba3ae8b30485830dc1dc578b2f921b1b65cb2a391cb063c0f1b6106]\")\n )\n )\n )\n )\n )\n )\n )\n ),\n Enum<1u8>(\n 20160u32\n )\n )\n;\nSET_METADATA\n Address(\"account_rdx12xek3geay25lktmk5zyplc7z7mg5xe8ldh48ta4mkcd9q0v0q6l8y6\")\n \"owner_keys\"\n Enum<143u8>(\n Array(\n Enum<1u8>(\n Bytes(\"e2e27b925c7d98ebe436172f00b024862127b26b40decd416ca41cdb48\")\n )\n )\n )\n;\n", + "blobs": [] + }, + { + "transactionManifest": "CALL_METHOD\n Address(\"accesscontroller_rdx1cv93xuha64eay8ctkx9km0el2jgkuh6gqlwec7tzecccyu0rj37xak\")\n \"initiate_recovery_as_recovery\"\n Tuple(\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n )\n ),\n Enum<1u8>(\n 20160u32\n )\n )\n;\nCALL_METHOD\n Address(\"accesscontroller_rdx1cv93xuha64eay8ctkx9km0el2jgkuh6gqlwec7tzecccyu0rj37xak\")\n \"quick_confirm_recovery_role_recovery_proposal\"\n Tuple(\n Tuple(\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n ),\n Enum<2u8>(\n Enum<1u8>(\n Array(\n Enum<0u8>(\n Enum<2u8>(\n 0u8,\n Array()\n )\n ),\n Enum<0u8>(\n Enum<4u8>(\n Array(\n Enum<0u8>(\n NonFungibleGlobalId(\"resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[388cd2d9ce11b878ba78fd193b5c5b34a8a497eb6cf9f0b4aac5a72a8a]\")\n )\n )\n )\n )\n )\n )\n )\n ),\n Enum<1u8>(\n 20160u32\n )\n )\n;\n", + "blobs": [] + } + ] +} \ No newline at end of file diff --git a/fixtures/vector/wallet_interactions_dapp_to_wallet.json b/fixtures/models/interaction/wallet_interactions_dapp_to_wallet.json similarity index 100% rename from fixtures/vector/wallet_interactions_dapp_to_wallet.json rename to fixtures/models/interaction/wallet_interactions_dapp_to_wallet.json diff --git a/fixtures/vector/wallet_interactions_wallet_to_dapp.json b/fixtures/models/interaction/wallet_interactions_wallet_to_dapp.json similarity index 100% rename from fixtures/vector/wallet_interactions_wallet_to_dapp.json rename to fixtures/models/interaction/wallet_interactions_wallet_to_dapp.json diff --git a/fixtures/vector/big_profile_100_accounts.json b/fixtures/models/profile/big_profile_100_accounts.json similarity index 100% rename from fixtures/vector/big_profile_100_accounts.json rename to fixtures/models/profile/big_profile_100_accounts.json diff --git a/fixtures/vector/huge_profile_1000_accounts.json b/fixtures/models/profile/huge_profile_1000_accounts.json similarity index 100% rename from fixtures/vector/huge_profile_1000_accounts.json rename to fixtures/models/profile/huge_profile_1000_accounts.json diff --git a/fixtures/vector/multi_profile_snapshots_test_version_100_patch_after_app_version_120.json b/fixtures/models/profile/multi_profile_snapshots_test_version_100_patch_after_app_version_120.json similarity index 100% rename from fixtures/vector/multi_profile_snapshots_test_version_100_patch_after_app_version_120.json rename to fixtures/models/profile/multi_profile_snapshots_test_version_100_patch_after_app_version_120.json diff --git a/fixtures/vector/only_plaintext_profile_snapshot_version_100.json b/fixtures/models/profile/only_plaintext_profile_snapshot_version_100.json similarity index 100% rename from fixtures/vector/only_plaintext_profile_snapshot_version_100.json rename to fixtures/models/profile/only_plaintext_profile_snapshot_version_100.json diff --git a/fixtures/vector/profile_encrypted_by_password_empty.json b/fixtures/models/profile/profile_encrypted_by_password_empty.json similarity index 100% rename from fixtures/vector/profile_encrypted_by_password_empty.json rename to fixtures/models/profile/profile_encrypted_by_password_empty.json diff --git a/fixtures/vector/profile_encrypted_by_password_of_babylon.json b/fixtures/models/profile/profile_encrypted_by_password_of_babylon.json similarity index 100% rename from fixtures/vector/profile_encrypted_by_password_of_babylon.json rename to fixtures/models/profile/profile_encrypted_by_password_of_babylon.json diff --git a/fixtures/vector/security_questions_factor_source_sample.json b/fixtures/models/profile_submodels/security_questions_factor_source_sample.json similarity index 100% rename from fixtures/vector/security_questions_factor_source_sample.json rename to fixtures/models/profile_submodels/security_questions_factor_source_sample.json diff --git a/fixtures/vector/security_questions_factor_source_sample_other.json b/fixtures/models/profile_submodels/security_questions_factor_source_sample_other.json similarity index 100% rename from fixtures/vector/security_questions_factor_source_sample_other.json rename to fixtures/models/profile_submodels/security_questions_factor_source_sample_other.json diff --git a/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_securified_account_amount_42.rtm b/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_securified_account_amount_42.rtm new file mode 100644 index 000000000..78b857b4a --- /dev/null +++ b/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_securified_account_amount_42.rtm @@ -0,0 +1,120 @@ +CALL_METHOD + Address("identity_rdx12tw6rt9c4l56rz6p866e35tmzp556nymxmpj8hagfewq82kspctdyw") + "securify" +; +TAKE_FROM_WORKTOP + Address("resource_rdx1nfxxxxxxxxxxdntwnrxxxxxxxxx002876444928xxxxxxxxxdntwnr") + Decimal("1") + Bucket("bucket1") +; +ALLOCATE_GLOBAL_ADDRESS + Address("package_rdx1pkgxxxxxxxxxcntrlrxxxxxxxxx000648572295xxxxxxxxxcntrlr") + "AccessController" + AddressReservation("reservation1") + NamedAddress("address1") +; +CREATE_ACCESS_CONTROLLER + Bucket("bucket1") + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ) + Enum<1u8>( + 20160u32 + ) + Enum<1u8>( + AddressReservation("reservation1") + ) +; +SET_METADATA + Address("identity_rdx12tw6rt9c4l56rz6p866e35tmzp556nymxmpj8hagfewq82kspctdyw") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("675506ad8d7ce4c602cb06c593c0f10e1cc4dcdf2c4144360ef33ebeef") + ) + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgmx69r8532n7e0w6sgs8lrctmdzsmylak75a0khwmp55pau5p8pr") + "create_proof" +; +CALL_METHOD + Address("account_rdx12xek3geay25lktmk5zyplc7z7mg5xe8ldh48ta4mkcd9q0v0q6l8y6") + "withdraw" + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("42") +; +TAKE_FROM_WORKTOP + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("42") + Bucket("bucket2") +; +CALL_METHOD + NamedAddress("address1") + "contribute_recovery_fee" + Bucket("bucket2") +; \ No newline at end of file diff --git a/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_unsecurified_account.rtm b/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_unsecurified_account.rtm new file mode 100644 index 000000000..dd59018d6 --- /dev/null +++ b/fixtures/transaction/create_access_controller_for_persona_with_ac_xrd_vault_top_up_by_unsecurified_account.rtm @@ -0,0 +1,116 @@ +CALL_METHOD + Address("identity_rdx12tw6rt9c4l56rz6p866e35tmzp556nymxmpj8hagfewq82kspctdyw") + "securify" +; +TAKE_FROM_WORKTOP + Address("resource_rdx1nfxxxxxxxxxxdntwnrxxxxxxxxx002876444928xxxxxxxxxdntwnr") + Decimal("1") + Bucket("bucket1") +; +ALLOCATE_GLOBAL_ADDRESS + Address("package_rdx1pkgxxxxxxxxxcntrlrxxxxxxxxx000648572295xxxxxxxxxcntrlr") + "AccessController" + AddressReservation("reservation1") + NamedAddress("address1") +; +CREATE_ACCESS_CONTROLLER + Bucket("bucket1") + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ) + Enum<1u8>( + 20160u32 + ) + Enum<1u8>( + AddressReservation("reservation1") + ) +; +SET_METADATA + Address("identity_rdx12tw6rt9c4l56rz6p866e35tmzp556nymxmpj8hagfewq82kspctdyw") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("675506ad8d7ce4c602cb06c593c0f10e1cc4dcdf2c4144360ef33ebeef") + ) + ) + ) +; +CALL_METHOD + Address("account_rdx12y02nen8zjrq0k0nku98shjq7n05kvl3j9m5d3a6cpduqwzgmenjq7") + "withdraw" + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("100") +; +TAKE_FROM_WORKTOP + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("100") + Bucket("bucket2") +; +CALL_METHOD + NamedAddress("address1") + "contribute_recovery_fee" + Bucket("bucket2") +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C.rtm b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C.rtm new file mode 100644 index 000000000..acfff3388 --- /dev/null +++ b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C.rtm @@ -0,0 +1,171 @@ +SET_METADATA + Address("account_rdx12xq83qxwf09eqquqfdj8rv004attq5tgxejkn59rwu588jprdy0xcg") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("cb3f6086cd08a1d0ab10139a9c6d191783edb534059f7b4716dc5d239e") + ) + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "initiate_recovery_as_primary" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "quick_confirm_primary_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield.rtm b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield.rtm new file mode 100644 index 000000000..ef7959202 --- /dev/null +++ b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield.rtm @@ -0,0 +1,191 @@ +SET_METADATA + Address("account_rdx12xq83qxwf09eqquqfdj8rv004attq5tgxejkn59rwu588jprdy0xcg") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("cb3f6086cd08a1d0ab10139a9c6d191783edb534059f7b4716dc5d239e") + ) + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "initiate_recovery_as_primary" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "quick_confirm_primary_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "create_proof" +; +CALL_METHOD + Address("account_rdx12xq83qxwf09eqquqfdj8rv004attq5tgxejkn59rwu588jprdy0xcg") + "withdraw" + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("10") +; +TAKE_FROM_WORKTOP + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("10") + Bucket("bucket1") +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "contribute_recovery_fee" + Bucket("bucket1") +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield_with_xrd_lock.rtm b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield_with_xrd_lock.rtm new file mode 100644 index 000000000..e0e42b7b0 --- /dev/null +++ b/fixtures/transaction/update_shield_of_account_init_with_P_confirm_with_C_with_top_up_where_payer_is_entity_applying_shield_with_xrd_lock.rtm @@ -0,0 +1,196 @@ +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "lock_recovery_fee" + Decimal("9") +; +SET_METADATA + Address("account_rdx12xq83qxwf09eqquqfdj8rv004attq5tgxejkn59rwu588jprdy0xcg") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("cb3f6086cd08a1d0ab10139a9c6d191783edb534059f7b4716dc5d239e") + ) + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "initiate_recovery_as_primary" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "quick_confirm_primary_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 2u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[2dabcc6872c45a625bccc21be9e666bfbc62b1f87a16f3848dd877ba22]") + ), + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[7225b29de13d7d06e0e9f406fe15165677573c9106ee036ad52bee2864]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[31262cc8dc5e9a49d1fe0ea8e60a17ef36d1ea857db94cca3e1e2a52dd]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "create_proof" +; +CALL_METHOD + Address("account_rdx12xq83qxwf09eqquqfdj8rv004attq5tgxejkn59rwu588jprdy0xcg") + "withdraw" + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("10") +; +TAKE_FROM_WORKTOP + Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + Decimal("10") + Bucket("bucket1") +; +CALL_METHOD + Address("accesscontroller_rdx1cdgcq7yqee9uhyqrsp9kgud3a7h4dvz3dqmx26ws5dmjsu7g3zg23g") + "contribute_recovery_fee" + Bucket("bucket1") +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_C.rtm b/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_C.rtm new file mode 100644 index 000000000..607708056 --- /dev/null +++ b/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_C.rtm @@ -0,0 +1,159 @@ +SET_METADATA + Address("identity_rdx12fczzwcn62phgf099l2d2l2huz7rag7zglujrvc5cc0z9szs2dzevj") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("675506ad8d7ce4c602cb06c593c0f10e1cc4dcdf2c4144360ef33ebeef") + ) + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "initiate_recovery_as_primary" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "quick_confirm_primary_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_T.rtm b/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_T.rtm new file mode 100644 index 000000000..2f3b55cbe --- /dev/null +++ b/fixtures/transaction/update_shield_of_persona_init_with_P_confirm_with_T.rtm @@ -0,0 +1,74 @@ +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "initiate_recovery_as_primary" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_C.rtm b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_C.rtm new file mode 100644 index 000000000..05b014baa --- /dev/null +++ b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_C.rtm @@ -0,0 +1,159 @@ +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "initiate_recovery_as_recovery" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "quick_confirm_recovery_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +SET_METADATA + Address("identity_rdx12fczzwcn62phgf099l2d2l2huz7rag7zglujrvc5cc0z9szs2dzevj") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("675506ad8d7ce4c602cb06c593c0f10e1cc4dcdf2c4144360ef33ebeef") + ) + ) + ) +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_P.rtm b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_P.rtm new file mode 100644 index 000000000..05b014baa --- /dev/null +++ b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_P.rtm @@ -0,0 +1,159 @@ +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "initiate_recovery_as_recovery" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "quick_confirm_recovery_role_recovery_proposal" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; +SET_METADATA + Address("identity_rdx12fczzwcn62phgf099l2d2l2huz7rag7zglujrvc5cc0z9szs2dzevj") + "owner_keys" + Enum<143u8>( + Array( + Enum<1u8>( + Bytes("675506ad8d7ce4c602cb06c593c0f10e1cc4dcdf2c4144360ef33ebeef") + ) + ) + ) +; \ No newline at end of file diff --git a/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_T.rtm b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_T.rtm new file mode 100644 index 000000000..64d011623 --- /dev/null +++ b/fixtures/transaction/update_shield_of_persona_init_with_R_confirm_with_T.rtm @@ -0,0 +1,74 @@ +CALL_METHOD + Address("accesscontroller_rdx1cdf8qgfmz0fgxap9u5haf4ta2lstc04rcfrljgdnznrpugkqv2wudm") + "initiate_recovery_as_recovery" + Tuple( + Tuple( + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 1u8, + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[99b417749d9022e73a6d2e025648a928ffbc499be8dc9e55eda900b11f]") + ) + ) + ) + ), + Enum<0u8>( + Enum<4u8>( + Array() + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[97d5d7196e49781708520322aaf5872214d854122600dd0125c837aefe]") + ) + ) + ) + ) + ) + ) + ), + Enum<2u8>( + Enum<1u8>( + Array( + Enum<0u8>( + Enum<2u8>( + 0u8, + Array() + ) + ), + Enum<0u8>( + Enum<4u8>( + Array( + Enum<0u8>( + NonFungibleGlobalId("resource_rdx1nfxxxxxxxxxxed25sgxxxxxxxxx002236757237xxxxxxxxxed25sg:[0b9bdb05d848b70041d7ed45c28dd9d6743a19eb129524d1c623b31784]") + ) + ) + ) + ) + ) + ) + ) + ), + Enum<1u8>( + 20160u32 + ) + ) +; \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileTest.kt index 009443ab8..e6d718c2b 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileTest.kt @@ -126,7 +126,7 @@ class ProfileTest : SampleTestable { @Test fun testCheckIfProfileJsonContainsLegacyP2PLinksWhenP2PLinksArePresent() { - val json = File("../../" + "fixtures/vector/only_plaintext_profile_snapshot_version_100.json").readText() + val json = File("../../" + "fixtures/models/profile/only_plaintext_profile_snapshot_version_100.json").readText() assertEquals( true, Profile.checkIfProfileJsonContainsLegacyP2PLinks(json) @@ -143,7 +143,7 @@ class ProfileTest : SampleTestable { @Test fun testCheckIfEncryptedProfileJsonContainsLegacyP2PLinksWhenP2PLinksArePresent() { - val json = File("../../" + "fixtures/vector/profile_encrypted_by_password_of_babylon.json").readText() + val json = File("../../" + "fixtures/models/profile/profile_encrypted_by_password_of_babylon.json").readText() assertEquals( true, Profile.checkIfEncryptedProfileJsonContainsLegacyP2PLinks(json, "babylon") diff --git a/makefile b/makefile index 272d96e29..82c825099 100644 --- a/makefile +++ b/makefile @@ -15,3 +15,7 @@ test_mac: test_mac_build: ./scripts/ios/test.sh --build + +clean: + cargo clean + rm cobertura.xml 2> /dev/null || true