diff --git a/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyProtocol.swift b/Sources/XyoClient/BoundWitness/Body/BoundWitnessBody.swift similarity index 76% rename from Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyProtocol.swift rename to Sources/XyoClient/BoundWitness/Body/BoundWitnessBody.swift index ed5f3da..a19a2f0 100644 --- a/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyProtocol.swift +++ b/Sources/XyoClient/BoundWitness/Body/BoundWitnessBody.swift @@ -1,9 +1,10 @@ import Foundation -public protocol XyoBoundWitnessBodyProtocol { +public protocol BoundWitnessBody { var addresses: [String] { get set } var payload_hashes: [String] { get set } var payload_schemas: [String] { get set } var previous_hashes: [String?] { get set } var query: String? { get set } + var schema: String { get set } } diff --git a/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyJson.swift b/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyJson.swift index 41d5eaf..0d972ac 100644 --- a/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyJson.swift +++ b/Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyJson.swift @@ -1,6 +1,6 @@ import Foundation -public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable, Decodable { +public class BoundWitnessBodyJson: BoundWitnessBody, Encodable, Decodable { enum CodingKeys: String, CodingKey { case addresses case payload_hashes diff --git a/Sources/XyoClient/BoundWitness/BoundWitness.swift b/Sources/XyoClient/BoundWitness/BoundWitness.swift index a671629..2616cb4 100644 --- a/Sources/XyoClient/BoundWitness/BoundWitness.swift +++ b/Sources/XyoClient/BoundWitness/BoundWitness.swift @@ -2,7 +2,7 @@ import Foundation let BoundWitnessSchema = "network.xyo.boundwitness" -public class BoundWitness: Payload, XyoBoundWitnessBodyProtocol, XyoBoundWitnessMetaProtocol, +public class BoundWitness: Payload, BoundWitnessBody, BoundWitnessMeta, Decodable { diff --git a/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift b/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift index e67af28..1773233 100644 --- a/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift +++ b/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift @@ -30,8 +30,8 @@ public class BoundWitnessBuilder { return self } - private func hashableFields() -> XyoBoundWitnessBodyJson { - return XyoBoundWitnessBodyJson( + private func hashableFields() -> BoundWitnessBodyJson { + return BoundWitnessBodyJson( addresses: _accounts.map { witness in witness.address }, payload_hashes: _payload_hashes, payload_schemas: _payload_schemas, diff --git a/Sources/XyoClient/BoundWitness/BoundWitnessJson.swift b/Sources/XyoClient/BoundWitness/BoundWitnessJson.swift index cf31514..f214901 100644 --- a/Sources/XyoClient/BoundWitness/BoundWitnessJson.swift +++ b/Sources/XyoClient/BoundWitness/BoundWitnessJson.swift @@ -1,10 +1,9 @@ import Foundation -public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaProtocol { +public class XyoBoundWitnessJson: BoundWitnessBodyJson, BoundWitnessMeta { enum CodingKeys: String, CodingKey { case _client case _hash - case _previous_hash case _signatures case addresses case payload_hashes @@ -17,7 +16,6 @@ public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaPr public var _client: String? public var _hash: String? public var _signatures: [String]? - public var _previous_hash: String? public var _query: String? func encodeMetaFields(_ container: inout KeyedEncodingContainer) throws { diff --git a/Sources/XyoClient/BoundWitness/Meta/BoundWitnessMetaProtocol.swift b/Sources/XyoClient/BoundWitness/Meta/BoundWitnessMeta.swift similarity index 74% rename from Sources/XyoClient/BoundWitness/Meta/BoundWitnessMetaProtocol.swift rename to Sources/XyoClient/BoundWitness/Meta/BoundWitnessMeta.swift index 989b906..46a20a0 100644 --- a/Sources/XyoClient/BoundWitness/Meta/BoundWitnessMetaProtocol.swift +++ b/Sources/XyoClient/BoundWitness/Meta/BoundWitnessMeta.swift @@ -1,6 +1,6 @@ import Foundation -public protocol XyoBoundWitnessMetaProtocol { +public protocol BoundWitnessMeta { var _client: String? { get set } var _hash: String? { get set } var _signatures: [String]? { get set } diff --git a/Sources/XyoClient/Payload/Payload.swift b/Sources/XyoClient/Payload/Payload.swift index 3caf114..c935ca9 100644 --- a/Sources/XyoClient/Payload/Payload.swift +++ b/Sources/XyoClient/Payload/Payload.swift @@ -23,11 +23,26 @@ extension Payload { public func hash() throws -> Data { let encoder = JSONEncoder() encoder.outputFormatting = .sortedKeys + + // Encode `self` to JSON data let data = try encoder.encode(self) - guard let str = String(data: data, encoding: .utf8) else { + // Decode the JSON into a dictionary and filter keys + guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { throw BoundWitnessBuilderError.encodingError } - return try str.sha256() + + let filteredJSON = jsonObject.filter { !$0.key.hasPrefix("_") } + + // Encode the filtered dictionary back into JSON data + let filteredData = try JSONSerialization.data(withJSONObject: filteredJSON, options: [.sortedKeys]) + + // Convert the JSON data into a string + guard let jsonString = String(data: filteredData, encoding: .utf8) else { + throw BoundWitnessBuilderError.encodingError + } + + // Hash the JSON string + return try jsonString.sha256() } } diff --git a/Tests/XyoClientTests/BoundWitness.swift b/Tests/XyoClientTests/BoundWitness.swift index e3de485..b2d052a 100644 --- a/Tests/XyoClientTests/BoundWitness.swift +++ b/Tests/XyoClientTests/BoundWitness.swift @@ -33,4 +33,13 @@ final class BoundWitnessTests: XCTestCase { let (bwJson, _) = try bw.build() XCTAssertEqual(bwJson._hash, "a5bd50ec40626d390017646296f6a6ac2938ff2e952b2a27b1467a7ef44cdf35") } + + func testPayload_hash_returnsExpectedHashWhenNested() throws { + let hash = try BoundWitnessBuilder.hash(testPayload2) + XCTAssertEqual(hash, testPayload2Hash) + let address = Account.fromPrivateKey(key: testVectorPrivateKey.hexToData()) + let bw = try BoundWitnessBuilder().signer(address).payload("network.xyo.test", testPayload2) + let (bwJson, _) = try bw.build() + XCTAssertEqual(bwJson._hash, "a5bd50ec40626d390017646296f6a6ac2938ff2e952b2a27b1467a7ef44cdf35") + } }