@@ -9,22 +9,13 @@ public typealias SubnetID = BigInt
99public enum BlockSignature : Hashable {
1010 case single( Signature )
1111 case multi( [ Signature ] )
12-
13- func toHexString( ) -> String {
14- switch self {
15- case . single( let signature) : signature. toHexString ( )
16- case . multi( let signatures) : " Multi-signatures not implemented "
17- }
18- }
1912}
2013
2114public struct Block {
22- public typealias Signature = BlockSignature
23-
2415 public let rawData : RawBlockData
2516 public let opening : Bool
2617 public let hash : String
27- public let signature : Signature
18+ public let signature : BlockSignature
2819
2920 public enum Version : Int , CaseIterable {
3021 case v1
@@ -56,20 +47,15 @@ public struct Block {
5647 let hash = try rawBlock. hash ( )
5748 let hashBytes = try hash. toBytes ( )
5849
59- let verifiedSignature : Signature
50+ let verifiedSignature : BlockSignature
6051 if let signature = signature {
61- switch signature {
62- case . single( let signature) :
63- let verified = try rawBlock. signer. verify ( data: Data ( hashBytes) , signature: signature)
64- guard verified else {
65- throw BlockError . invalidSignature
66- }
67- verifiedSignature = . single( signature)
68- case . multi:
69- throw NSError ( domain: " Multi-signatures not implemented " , code: 0 )
52+ let verified = try rawBlock. signer. account. verify ( data: Data ( hashBytes) , signature: signature)
53+ guard verified else {
54+ throw BlockError . invalidSignature
7055 }
56+ verifiedSignature = . single( signature)
7157 } else {
72- verifiedSignature = . single( try rawBlock. signer. sign ( data: Data ( hashBytes) ) )
58+ verifiedSignature = . single( try rawBlock. signer. account . sign ( data: Data ( hashBytes) ) )
7359 }
7460
7561 self . rawData = rawBlock
@@ -122,7 +108,7 @@ public struct Block {
122108 }
123109
124110 let rawBlock : RawBlockData
125- let signature : Signature
111+ let signature : BlockSignature
126112 let opening : Bool
127113
128114 switch version {
@@ -134,6 +120,15 @@ public struct Block {
134120 self . opening = opening
135121 self . hash = try rawBlock. hash ( )
136122 self . signature = signature
123+
124+ // Verify block signature
125+ switch signature {
126+ case . single( let signature) :
127+ let verified = try rawBlock. signer. account. verify ( data: Data ( try hash. toBytes ( ) ) , signature: signature)
128+ if !verified { throw BlockError . invalidSignature }
129+ case . multi:
130+ break // currently not supported
131+ }
137132 }
138133
139134 public func toAsn1( ) throws -> [ ASN1 ] {
@@ -143,7 +138,7 @@ public struct Block {
143138 case . single( let signature) :
144139 rawASN1 + [ . octetString( . init( signature) ) ]
145140 case . multi( let signatures) :
146- rawASN1 + signatures. map { . octetString( . init ( $0) ) }
141+ rawASN1 + [ . sequence ( signatures. map { . octetString( Data ( $0) ) } ) ]
147142 }
148143 }
149144
@@ -163,7 +158,7 @@ public struct Block {
163158
164159 // MARK: Helper
165160
166- private static func blockDataV1( for sequence: [ ASN1 ] ) throws -> ( RawBlockData , Signature , Bool ) {
161+ private static func blockDataV1( for sequence: [ ASN1 ] ) throws -> ( RawBlockData , BlockSignature , Bool ) {
167162 guard let network = sequence [ 1 ] . integerValue else {
168163 throw BlockError . invalidNetwork
169164 }
@@ -216,7 +211,7 @@ public struct Block {
216211 previous: previousHash,
217212 network: network,
218213 subnet: subnet,
219- signer: signer,
214+ signer: . single ( signer) ,
220215 account: account,
221216 operations: operations,
222217 created: anyTime. zonedDate. utcDate
@@ -225,7 +220,7 @@ public struct Block {
225220 return ( rawBlock, . single( signature. bytes) , opening)
226221 }
227222
228- private static func blockDataV2( for sequence: [ ASN1 ] ) throws -> ( RawBlockData , Signature , Bool ) {
223+ private static func blockDataV2( for sequence: [ ASN1 ] ) throws -> ( RawBlockData , BlockSignature , Bool ) {
229224 guard let network = sequence [ 0 ] . integerValue else {
230225 throw BlockError . invalidNetwork
231226 }
@@ -249,14 +244,13 @@ public struct Block {
249244 let account = try Account ( data: accountData)
250245
251246 let signerContainer = sequence [ 6 - offset]
252- let signer : Account
247+ let signer : RawBlockData . Signer
253248 if signerContainer. isNull {
254- signer = account
249+ signer = . single ( account)
255250 } else if let signerData = signerContainer. octetStringValue {
256- signer = try Account ( data: signerData)
251+ signer = . single ( try Account ( data: signerData) )
257252 } else {
258- // TODO: implement 'this.signer = parseBlockSignerFieldContainer(signersContainer).parsed;'
259- throw NSError ( domain: " Multi-signatures not implemented " , code: 0 )
253+ signer = try parseMultiSig ( signerContainer)
260254 }
261255
262256 guard let previousHashData = sequence [ 7 - offset] . octetStringValue else {
@@ -270,11 +264,16 @@ public struct Block {
270264 let operations = try operationsSequence. map { try BlockOperationBuilder . create ( from: $0) }
271265
272266 let signatureContainer = sequence [ 9 - offset]
273- let signature : Signature
267+ let signature : BlockSignature
274268 if let signatureValue = signatureContainer. octetStringValue {
275269 signature = . single( signatureValue. bytes)
270+ } else if let signatureValues = signatureContainer. sequenceValue {
271+ let signatures = signatureValues. compactMap { $0. octetStringValue? . bytes }
272+ guard !signatures. isEmpty && signatures. count == signatureValues. count else {
273+ throw BlockError . missingMultiSigSignatures
274+ }
275+ signature = . multi( signatures)
276276 } else {
277- // TODO: implement 'assertBlockSignatureField(signatureContainer);'
278277 throw BlockError . invalidSignature
279278 }
280279
@@ -296,12 +295,43 @@ public struct Block {
296295 return ( rawBlock, signature, opening)
297296 }
298297
299- private static func parseIdempotent( from asn1: ASN1 ) throws -> String ? {
300- guard let idempotentData = asn1. octetStringValue else { return nil }
298+ private static func parseMultiSig( _ container: ASN1 , depth: Int = 0 ) throws -> RawBlockData . Signer {
299+ guard depth <= 3 else {
300+ throw BlockError . invalidMultiSigSignersDepth
301+ }
302+
303+ guard let sequence = container. sequenceValue, sequence. count == 2 else {
304+ throw BlockError . invalidMultiSigSequence
305+ }
306+
307+ guard let multiSigData = sequence [ 0 ] . octetStringValue else {
308+ throw BlockError . invalidMultiSigAccount
309+ }
310+
311+ let account = try Account ( data: multiSigData)
301312
302- guard let idempotentString = String ( data : idempotentData , encoding : . utf8 ) else {
303- throw BlockError . invalidIdempotentData
313+ guard let signersSequence = sequence [ 1 ] . sequenceValue else {
314+ throw BlockError . missingMultiSigSigners
304315 }
316+
317+ var signers = [ RawBlockData . Signer] ( )
318+
319+ for item in signersSequence {
320+ if let accountData = item. octetStringValue {
321+ signers. append ( . single( try Account ( data: accountData) ) )
322+ } else if item. sequenceValue != nil {
323+ signers. append ( try parseMultiSig ( item, depth: depth + 1 ) )
324+ } else {
325+ throw BlockError . invalidMultiSigSigners
326+ }
327+ }
328+
329+ return . multi( account, signers)
330+ }
331+
332+ private static func parseIdempotent( from asn1: ASN1 ) throws -> String ? {
333+ guard let idempotentData = asn1. octetStringValue else { return nil }
334+ let idempotentString = String ( data: idempotentData, encoding: . utf8) ?? idempotentData. base64EncodedString ( )
305335 return idempotentString
306336 }
307337}
0 commit comments