Skip to content

Commit

Permalink
Merge pull request #39 from XYOracleNetwork/feature/updated-boundwitn…
Browse files Browse the repository at this point in the history
…ess-builder

Updated `BoundWitnessBuilder` & `Witness` Protocols
  • Loading branch information
JoelBCarter authored Nov 11, 2024
2 parents 2cc50fe + b3bb3e2 commit 8e8703f
Show file tree
Hide file tree
Showing 17 changed files with 268 additions and 67 deletions.
68 changes: 64 additions & 4 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -1,10 +1,70 @@
{
"version": 1,
"lineLength": 120,
"fileScopedDeclarationPrivacy": {
"accessLevel": "private"
},
"indentConditionalCompilationBlocks": true,
"indentSwitchCaseLabels": false,
"indentation": {
"spaces": 2
},
"lineBreakAroundMultilineExpressionChainComponents": false,
"lineBreakBeforeControlFlowKeywords": false,
"lineBreakBeforeEachArgument": false,
"lineBreakBeforeEachGenericRequirement": false,
"lineLength": 100,
"maximumBlankLines": 1,
"multiElementCollectionTrailingCommas": true,
"noAssignmentInExpressions": {
"allowedFunctions": [
"XCTAssertNoThrow"
]
},
"prioritizeKeepingFunctionOutputTogether": false,
"respectsExistingLineBreaks": true,
"rules": {
"OrderedImports": true
}
"AllPublicDeclarationsHaveDocumentation": false,
"AlwaysUseLiteralForEmptyCollectionInit": false,
"AlwaysUseLowerCamelCase": true,
"AmbiguousTrailingClosureOverload": true,
"BeginDocumentationCommentWithOneLineSummary": false,
"DoNotUseSemicolons": true,
"DontRepeatTypeInStaticProperties": true,
"FileScopedDeclarationPrivacy": true,
"FullyIndirectEnum": true,
"GroupNumericLiterals": true,
"IdentifiersMustBeASCII": true,
"NeverForceUnwrap": false,
"NeverUseForceTry": false,
"NeverUseImplicitlyUnwrappedOptionals": false,
"NoAccessLevelOnExtensionDeclaration": true,
"NoAssignmentInExpressions": true,
"NoBlockComments": true,
"NoCasesWithOnlyFallthrough": true,
"NoEmptyTrailingClosureParentheses": true,
"NoLabelsInCasePatterns": true,
"NoLeadingUnderscores": false,
"NoParensAroundConditions": true,
"NoPlaygroundLiterals": true,
"NoVoidReturnOnFunctionSignature": true,
"OmitExplicitReturns": false,
"OneCasePerLine": true,
"OneVariableDeclarationPerLine": true,
"OnlyOneTrailingClosureArgument": true,
"OrderedImports": true,
"ReplaceForEachWithForLoop": true,
"ReturnVoidInsteadOfEmptyTuple": true,
"TypeNamesShouldBeCapitalized": true,
"UseEarlyExits": false,
"UseExplicitNilCheckInConditions": true,
"UseLetInEveryBoundCaseVariable": true,
"UseShorthandTypeNames": true,
"UseSingleLinePropertyGetter": true,
"UseSynthesizedInitializer": true,
"UseTripleSlashForDocumentationComments": true,
"UseWhereClausesInForLoops": false,
"ValidateDocumentationComments": false
},
"spacesAroundRangeFormationOperators": false,
"tabWidth": 8,
"version": 1
}
91 changes: 91 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/XyoClient.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XyoClient"
BuildableName = "XyoClient"
BlueprintName = "XyoClient"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XyoClientTests"
BuildableName = "XyoClientTests"
BlueprintName = "XyoClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<EnvironmentVariables>
<EnvironmentVariable
key = "XYO_API_DOMAIN"
value = "http://localhost:8080"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "XYO_API_MODULE"
value = "Archivist"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XyoClient"
BuildableName = "XyoClient"
BlueprintName = "XyoClient"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
31 changes: 29 additions & 2 deletions Sources/XyoClient/ArchivistApi/ArchivistApiClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,33 @@ public class XyoArchivistApiClient {
}
}

public var url: String {
return "\(self.config.apiDomain)/\(self.config.apiModule)"
}

private init(_ config: XyoArchivistApiConfig) {
self.config = config
}

public func insert(payloads: [XyoBoundWitnessJson]) async throws -> XyoBoundWitnessJson {
// TODO: Build query bound witness
// Perform the request and await the result
let responseData = try await AF.request(
self.url,
method: .post,
parameters: payloads,
encoder: JSONParameterEncoder.default
)
.validate()
.serializingData()
.value

// Attempt to decode the response data into XyoBoundWitnessJson
let decodedResponse = try JSONDecoder().decode([XyoBoundWitnessJson].self, from: responseData)
// TODO: Return payloads instead once they're deserializable
return decodedResponse[0]
}

public func postBoundWitnesses(
_ entries: [XyoBoundWitnessJson]
) throws {
Expand All @@ -38,7 +61,7 @@ public class XyoArchivistApiClient {
) throws {
let body = entries
AF.request(
"\(self.config.apiDomain)/\(self.config.apiModule)",
self.url,
method: .post,
parameters: body,
encoder: JSONParameterEncoder.default
Expand Down Expand Up @@ -80,6 +103,10 @@ public class XyoArchivistApiClient {
}

extension XyoArchivistApiClient {
static fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
static fileprivate let queue = DispatchQueue(
label: "network.xyo.requests.queue",
qos: .utility,
attributes: [.concurrent]
)
static fileprivate let mainQueue = DispatchQueue.main
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable {
public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable, Decodable {
enum CodingKeys: String, CodingKey {
case addresses
case payload_hashes
Expand Down
5 changes: 2 additions & 3 deletions Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,19 @@ public class BoundWitnessBuilder {
}
}

public func build(_ previousHash: String? = nil) throws -> XyoBoundWitnessJson {
public func build(_ previousHash: String? = nil) throws -> (XyoBoundWitnessJson, [XyoPayload]) {
let bw = XyoBoundWitnessJson()
let hashable = hashableFields()
let hash = try BoundWitnessBuilder.hash(hashable)
bw._signatures = try self.sign(hash)
bw._hash = hash
bw._client = "swift"
bw._payloads = _payloads
bw._previous_hash = previousHash
bw.addresses = _witnesses.map { witness in witness?.addressHex! }
bw.previous_hashes = _previous_hashes
bw.payload_hashes = _payload_hashes
bw.payload_schemas = _payload_schemas
return bw
return (bw, _payloads)
}

static func hash<T: Encodable>(_ json: T) throws -> String {
Expand Down
3 changes: 0 additions & 3 deletions Sources/XyoClient/BoundWitness/BoundWitnessJson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaPr
enum CodingKeys: String, CodingKey {
case _client
case _hash
case _payloads
case _previous_hash
case _signatures
case addresses
Expand All @@ -16,14 +15,12 @@ public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaPr

public var _client: String?
public var _hash: String?
public var _payloads: [XyoPayload]?
public var _signatures: [String?]?
public var _previous_hash: String?

func encodeMetaFields(_ container: inout KeyedEncodingContainer<CodingKeys>) throws {
try container.encode(_client, forKey: ._client)
try container.encode(_hash, forKey: ._hash)
try container.encode(_payloads, forKey: ._payloads)
try container.encode(_signatures, forKey: ._signatures)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import Foundation
public protocol XyoBoundWitnessMetaProtocol {
var _client: String? { get set }
var _hash: String? { get set }
var _payloads: [XyoPayload]? { get set }
var _signatures: [String?]? { get set }
var _previous_hash: String? { get set }
}
20 changes: 15 additions & 5 deletions Sources/XyoClient/Payload/XyoPayload.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import Foundation

open class XyoPayload: Encodable {

public init(_ schema: String, _ previousHash: String? = nil) {
public init(_ schema: String) {
self.schema = schema.lowercased()
self.previousHash = previousHash
}

public var schema: String
public var previousHash: String?
}

extension XyoPayload {

/// 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 -> Data {
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
Expand Down
16 changes: 9 additions & 7 deletions Sources/XyoClient/XyoPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class XyoPanel {
self.init(archivists: [archivist], witnesses: witnesses ?? [])
}

public convenience init(observe: ((_ previousHash: String?) -> XyoEventPayload?)?) {
public convenience init(observe: (() -> XyoEventPayload?)?) {
if observe != nil {
var witnesses = [XyoWitness]()

Expand All @@ -46,7 +46,7 @@ public class XyoPanel {
}

public func event(_ event: String, _ closure: XyoPanelReportCallback?) throws -> [XyoPayload] {
try report([XyoEventWitness { previousHash in XyoEventPayload(event, previousHash) }], closure)
try report([XyoEventWitness { XyoEventPayload(event) }], closure)
}

public func report(
Expand All @@ -59,9 +59,9 @@ public class XyoPanel {
witnesses.append(contentsOf: self._witnesses)
let payloads = witnesses.map { witness in
witness.observe()
}
let bw = try BoundWitnessBuilder()
.payloads(payloads.compactMap { $0 })
}.flatMap({ $0 })
let (bw, _) = try BoundWitnessBuilder()
.payloads(payloads)
.witnesses(witnesses)
.build(_previous_hash)
self._previous_hash = bw._hash
Expand All @@ -86,8 +86,10 @@ public class XyoPanel {
}

struct Defaults {
static let apiModule = "Archivist"
static let apiDomain = "https://beta.api.archivist.xyo.network"
static let apiDomain =
ProcessInfo.processInfo.environment["XYO_API_DOMAIN"]
?? "https://beta.api.archivist.xyo.network"
static let apiModule = ProcessInfo.processInfo.environment["XYO_API_MODULE"] ?? "Archivist"
}

private static var defaultArchivist: XyoArchivistApiClient {
Expand Down
19 changes: 12 additions & 7 deletions Sources/XyoClient/XyoWitness/Basic/BasicWitness.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@ import Foundation

open class XyoBasicWitness: XyoWitness {

public init(_ observer: @escaping ObserverClosure) {
public typealias TPayloadOut = XyoPayload

public init(observer: @escaping ObserverClosure) {
_observer = observer
super.init()
}

public init(_ address: XyoAddress, _ observer: @escaping ObserverClosure) {
public init(address: XyoAddress, observer: @escaping ObserverClosure) {
_observer = observer
super.init(address)
super.init(address: address)
}

public typealias ObserverClosure = ((_ previousHash: String?) -> XyoPayload?)

private let _observer: ObserverClosure

override public func observe() -> XyoPayload? {
let payload = _observer(previousHash)
previousHash = try? payload?.hash().toHex()
return payload
override public func observe() -> [XyoPayload] {
if let payload = _observer(previousHash) {
previousHash = try? payload.hash().toHex()
return [payload]
} else {
return []
}
}
}
Loading

0 comments on commit 8e8703f

Please sign in to comment.