diff --git a/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift b/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift index 09cecd7..f36b0d7 100644 --- a/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift +++ b/Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift @@ -87,11 +87,37 @@ public class BoundWitnessBuilder { static func hash(_ json: T) throws -> String { let encoder = JSONEncoder() encoder.outputFormatting = .sortedKeys + + // Encode `self` to JSON data let data = try encoder.encode(json) - 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 + } + + 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 } - return try str.sha256().toHex() + + // Hash the JSON string + let prefixesRemoved = try jsonString.sha256().toHex() + print(prefixesRemoved) + let withoutPrefixesRemoved = data.sha256().toHex() + print(withoutPrefixesRemoved) + if prefixesRemoved != withoutPrefixesRemoved { + print("Error") + } + return prefixesRemoved } } diff --git a/Sources/XyoClient/Payload/Payload.swift b/Sources/XyoClient/Payload/Payload.swift index 724cca0..ddd610c 100644 --- a/Sources/XyoClient/Payload/Payload.swift +++ b/Sources/XyoClient/Payload/Payload.swift @@ -8,41 +8,7 @@ open class Payload: Encodable { } extension Payload { - - /// Generates a SHA-256 hash of the encoded representation of the instance. - /// - /// This method serializes the instance using JSON encoding with sorted keys, - /// converts the encoded data into a UTF-8 string, and then applies SHA-256 - /// hashing to generate a hash of the instance's contents. - /// - /// - Throws: - /// - `BoundWitnessBuilderError.encodingError` if the instance cannot be - /// converted to a UTF-8 string after encoding. - /// - Any error thrown by the `sha256()` function if the hashing process fails. - /// - Returns: A `Data` object containing the SHA-256 hash of the encoded instance. public func hash() throws -> String { - let encoder = JSONEncoder() - encoder.outputFormatting = .sortedKeys - - // Encode `self` to JSON data - let data = try encoder.encode(self) - - // 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 - } - - 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().toHex() + return try BoundWitnessBuilder.hash(self) } } diff --git a/Tests/XyoClientTests/BoundWitness.swift b/Tests/XyoClientTests/BoundWitness.swift index b2d052a..6825a9b 100644 --- a/Tests/XyoClientTests/BoundWitness.swift +++ b/Tests/XyoClientTests/BoundWitness.swift @@ -8,7 +8,7 @@ final class BoundWitnessTests: XCTestCase { ("testPayload_hash_returnsExpectedHash1", testPayload_hash_returnsExpectedHash1), ("testPayload_hash_returnsExpectedHash2", testPayload_hash_returnsExpectedHash2), ] - + override func setUp() { super.setUp() // Ensure previousHash = nil for tests addresses @@ -22,7 +22,8 @@ final class BoundWitnessTests: XCTestCase { let bw = try BoundWitnessBuilder().signer(address).payload( "network.xyo.test", TestPayload1("network.xyo.test")) let (bwJson, _) = try bw.build() - XCTAssertEqual(bwJson._hash, "a5bd50ec40626d390017646296f6a6ac2938ff2e952b2a27b1467a7ef44cdf35") + XCTAssertEqual( + bwJson._hash, "a5bd50ec40626d390017646296f6a6ac2938ff2e952b2a27b1467a7ef44cdf35") } func testPayload_hash_returnsExpectedHash2() throws { @@ -31,15 +32,17 @@ final class BoundWitnessTests: XCTestCase { 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") + 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") + XCTAssertEqual( + bwJson._hash, "a5bd50ec40626d390017646296f6a6ac2938ff2e952b2a27b1467a7ef44cdf35") } }