Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ethereum export #60

Merged
merged 46 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3d307f8
Made methods public
Oct 31, 2021
3570896
Runtime Metadata V14 support
Nov 30, 2021
a5e6410
Fixed StorageEntryType visibility
Nov 30, 2021
7ea26fc
Merge branch 'websockets-make-subscription-public' into runtime-metad…
Nov 30, 2021
bf8425a
Provided initial naming
Nov 30, 2021
5e91e74
Fixed tuple resolve
Nov 30, 2021
1303a83
Added final working prototype, fixed tests build
Dec 15, 2021
d81aaa2
Fixed RuntimeCall
Dec 16, 2021
a876410
Fixed known types
Dec 16, 2021
fd954be
Fixed call type name
Dec 17, 2021
64c1ec8
Resolved backward mapping
Dec 17, 2021
6c60c2b
Fixed most known types
Dec 20, 2021
6e3b1b3
Fixed MultiAddress type for resolving
Dec 20, 2021
00898c7
Fixed generic naming
Dec 20, 2021
50c21b1
Removed versions for IrohaCrypto
Dec 21, 2021
bc98d91
Returned ARM64 target
Dec 21, 2021
b9aab31
Updates for M1 support
Dec 21, 2021
be2d169
Fixed base types and enum generation for retrieving fee
Dec 21, 2021
308eda9
Removed backward mapping for biguint-keyed types
Dec 22, 2021
72ed445
Updated deps
Dec 23, 2021
214a3f1
Fixing tests
Dec 23, 2021
1f0dd4d
Finalized tests
Dec 27, 2021
ce5c18f
Returned parsing bytes as string array
Dec 28, 2021
2bca4c0
Added support for signed integers
Dec 29, 2021
8177055
moved heavyweight RuntimeSchemaNodeFactory to end of factory chain to…
bnsports Jan 10, 2022
81cc1f6
Reverted back to array of string instead of hex
Jan 11, 2022
fe88a54
fixed uint decoding
bnsports Jan 17, 2022
4179ab3
runtimeschemanodefactory to first step
bnsports Jan 17, 2022
4aa9efc
nMap decoding
bnsports Jan 19, 2022
8554c66
enum node encode null fix
bnsports Jan 19, 2022
72e9d5b
removed generics from name generation to support similar types in dif…
bnsports Jan 21, 2022
f9baf8e
fix enum Option type parsing
bnsports Jan 21, 2022
6b96fd3
Added support of overriden signed extensions in parachains
Jan 22, 2022
e5c4881
Fixes for Basilisk extrinsics
Jan 24, 2022
cba777a
Additional fixes for Moonbeam/Moonriver extrinsic build
Jan 24, 2022
52644e6
fixed generic handling
bnsports Jan 25, 2022
c99380c
reconnect to socket with dirrefent url
bnsports Feb 7, 2022
be89432
node reconnecting simplified solution
bnsports Feb 8, 2022
22ef3c1
socket reconnect
bnsports Feb 10, 2022
27c3351
WIP: extrinsic building fixed
posplaw Feb 10, 2022
2c3b262
Finalized Moonbeam/Moonriver extrinsic signature generating
posplaw Feb 11, 2022
36c8b48
Merge branch 'runtime-metadata-v14' into develop
bnsports Feb 16, 2022
3522a36
crashfix for reconnecting
bnsports Feb 16, 2022
a83147d
hardcoded ethereum testcase
bnsports Feb 16, 2022
46f08e3
ethereum export constant
Viscount88 Feb 17, 2022
bd20875
Merge branch 'develop' into feature/ethereum-export
bnsports Feb 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ public struct EcdsaKeypairFactory: DerivableSeedFactoryProtocol {

public init() {}

public func createKeypairFromSeed(_ seed: Data,
chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol {
public func createKeypairFromSeed(
_ seed: Data,
chaincodeList: [Chaincode]
) throws -> IRCryptoKeypairProtocol {
let childSeed = try deriveChildSeedFromParent(seed, chaincodeList: chaincodeList)
let childPrivateKey = try SECPrivateKey(rawData: childSeed)
return try internalFactory.derive(fromPrivateKey: childPrivateKey)
Expand Down
2 changes: 1 addition & 1 deletion FearlessUtils/Classes/Extrinsic/CryptoType+Extrinsic.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

extension CryptoType {
init?(onChainType: UInt8) {
public init?(onChainType: UInt8) {
switch onChainType {
case 0:
self = .ed25519
Expand Down
5 changes: 4 additions & 1 deletion FearlessUtils/Classes/Extrinsic/Extrinsic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,19 @@ public struct ExtrinsicSignature: Codable {
case address
case signature
case extra
case type
}

public let address: JSON
public let signature: JSON
public let extra: ExtrinsicSignedExtra
public let type: String

public init(address: JSON, signature: JSON, extra: ExtrinsicSignedExtra) {
public init(address: JSON, signature: JSON, extra: ExtrinsicSignedExtra, type: String) {
self.address = address
self.signature = signature
self.extra = extra
self.type = type
}
}

Expand Down
72 changes: 58 additions & 14 deletions FearlessUtils/Classes/Extrinsic/ExtrinsicBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,24 +189,45 @@ extension ExtrinsicBuilder: ExtrinsicBuilderProtocol {

let rawSignature = try signer(data)

let signature: MultiSignature

switch type {
case .sr25519:
signature = .sr25519(data: rawSignature)
case .ed25519:
signature = .ed25519(data: rawSignature)
case .ecdsa:
signature = .ecdsa(data: rawSignature)
var signatureJson = JSON.null
var signatureTypeString = KnownType.signature.rawValue

// Some networks like Moonbeam/Moonriver have signature as direct byte-array rather than MultiSignature enum
// Though they have MultiSignature enum in their metadata, check what signature type is used within extrinsic
// Otherwise provide default enum based MultiSignature behavior
if let extrinsicType = try? metadata.schemaResolver.typeMetadata(for: metadata.extrinsic.type) {
let signatureParam = extrinsicType.params.first { $0.name == "Signature" }
if let signatureType = try? metadata.schemaResolver.typeMetadata(for: signatureParam?.type) {
switch signatureType.def {
case .variant:
break
default:
signatureJson = try rawSignature.toScaleCompatibleJSON()
signatureTypeString = try metadata.schemaResolver.typeName(for: signatureType)
}
}
}

if signatureJson == .null {
let signature: MultiSignature
switch type {
case .sr25519:
signature = .sr25519(data: rawSignature)
case .ed25519:
signature = .ed25519(data: rawSignature)
case .ecdsa:
signature = .ecdsa(data: rawSignature)
}

let sigJson = try signature.toScaleCompatibleJSON()
signatureJson = try signature.toScaleCompatibleJSON()
}

let extra = ExtrinsicSignedExtra(era: era, nonce: nonce ?? 0, tip: tip)
self.signature = ExtrinsicSignature(
address: address,
signature: sigJson,
extra: extra
signature: signatureJson,
extra: extra,
type: signatureTypeString
)

return self
Expand All @@ -217,11 +238,34 @@ extension ExtrinsicBuilder: ExtrinsicBuilderProtocol {
metadata: RuntimeMetadata
) throws -> Data {
let call = try prepareExtrinsicCall(for: metadata)


Log.enable(kind: "DynamicScale")
let extrinsic = Extrinsic(signature: signature, call: call)

try encoder.append(extrinsic, ofType: GenericType.extrinsic.name)

let encoded = try encoder.encode()
Log.write("DynamicScale", message: "Extrinsic encoded: \(encoded.toHex(includePrefix: true))")
Log.disable(kind: "DynamicScale")

return encoded
}
}

return try encoder.encode()
struct Log {
private static var enabled: [String] = []

static func enable(kind: String) {
enabled.append(kind)
}

static func disable(kind: String) {
enabled.removeAll { $0 == kind }
}

static func write(_ kind: String, message: String) {
if enabled.contains(kind) {
print("[\(kind)] \(message)")
}
}
}
16 changes: 13 additions & 3 deletions FearlessUtils/Classes/Keystore/KeystoreBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ public class KeystoreBuilder {
}

extension KeystoreBuilder: KeystoreBuilding {
enum Constants {
static let ethereum = "ethereum"
}

public func with(name: String) -> Self {
self.name = name
return self
Expand All @@ -26,7 +30,7 @@ extension KeystoreBuilder: KeystoreBuilding {
return self
}

public func build(from data: KeystoreData, password: String?) throws -> KeystoreDefinition {
public func build(from data: KeystoreData, password: String?, isEthereum: Bool) throws -> KeystoreDefinition {
let scryptParameters = try ScryptParameters()

let scryptData: Data
Expand Down Expand Up @@ -64,17 +68,23 @@ extension KeystoreBuilder: KeystoreBuilding {
let pcksData = KeystoreConstants.pkcs8Header + secretKeyData +
KeystoreConstants.pkcs8Divider + data.publicKeyData
let encrypted = try NaclSecretBox.secretBox(message: pcksData, nonce: nonce, key: encryptionKey)

let encoded = scryptParameters.encode() + nonce + encrypted

let cryptoType = isEthereum ? Constants.ethereum : data.cryptoType.rawValue
let encodingType = [KeystoreEncodingType.scrypt.rawValue, KeystoreEncodingType.xsalsa.rawValue]
let encodingContent = [KeystoreEncodingContent.pkcs8.rawValue, data.cryptoType.rawValue]
let encodingContent = [KeystoreEncodingContent.pkcs8.rawValue, cryptoType]
let keystoreEncoding = KeystoreEncoding(content: encodingContent,
type: encodingType,
version: String(KeystoreConstants.version))

let isHardware: Bool? = isEthereum ? false : nil
let tags: [String]? = isEthereum ? [] : nil
let meta = KeystoreMeta(name: name,
createdAt: Int64(creationDate.timeIntervalSince1970),
genesisHash: genesisHash)
genesisHash: genesisHash,
isHardware: isHardware,
tags: tags)

return KeystoreDefinition(address: data.address,
encoded: encoded.base64EncodedString(),
Expand Down
2 changes: 1 addition & 1 deletion FearlessUtils/Classes/Keystore/KeystoreCommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public protocol KeystoreBuilding {
func with(creationDate: Date) -> Self
func with(genesisHash: String) -> Self

func build(from data: KeystoreData, password: String?) throws -> KeystoreDefinition
func build(from data: KeystoreData, password: String?, isEthereum: Bool) throws -> KeystoreDefinition
}

public enum KeystoreExtractorError: Error {
Expand Down
4 changes: 4 additions & 0 deletions FearlessUtils/Classes/Keystore/KeystoreDefinition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ public struct KeystoreMeta: Codable {
case name
case createdAt = "whenCreated"
case genesisHash
case isHardware
case tags
}

public let name: String?
public let createdAt: Int64?
public let genesisHash: String?
public let isHardware: Bool?
public let tags: [String]?
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import Starscream

extension WebSocketEngine: WebSocketDelegate {
public func didReceive(event: WebSocketEvent, client _: WebSocket) {
public func didReceive(event: WebSocketEvent, client _: WebSocket) {
mutex.lock()

switch event {
Expand Down
10 changes: 4 additions & 6 deletions FearlessUtils/Classes/Network/WebSocketEngine+Protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extension WebSocketEngine: JSONRPCEngine {
}

public func reconnect(url: URL) {
self.connection.disconnect()
self.connection.disconnect(closeCode: 0)

self.url = url
let request = URLRequest(url: url, timeoutInterval: 10)
Expand All @@ -81,15 +81,13 @@ extension WebSocketEngine: JSONRPCEngine {
certPinner: FoundationSecurity(),
compressionHandler: nil
)

let connection = WebSocket(request: request, engine: engine)
connection.forceDisconnect()
self.connection = connection

connection.delegate = self
connection.callbackQueue = Self.sharedProcessingQueue

self.changeState(.notConnected)
self.connectIfNeeded()

self.changeState(.connecting(attempt: 0))
}
}
3 changes: 0 additions & 3 deletions FearlessUtils/Classes/Network/WebSocketEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ public final class WebSocketEngine {
if let delegate = delegate {
let oldState = oldValue
let newState = state

completionQueue.async {
delegate.webSocketDidChangeState(engine: self, from: oldState, to: newState)
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions FearlessUtils/Classes/Runtime/KnownType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum KnownType: String, CaseIterable {
case phase = "frame_system::Phase"
case address = "sp_runtime::multiaddress::MultiAddress"
case signature = "sp_runtime::MultiSignature"
case extrinsic = "sp_runtime::generic::unchecked_extrinsic::UncheckedExtrinsic"
case addressId32 = "sp_core::crypto::AccountId32" // regular networks
case addressId20 = "account::AccountId20" // ethereum-based networks like Moonbeam/Moonriver

Expand Down
11 changes: 7 additions & 4 deletions FearlessUtils/Classes/Runtime/Metadata/ExtrinsicMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BigInt

public protocol RuntimeExtrinsicMetadata {
var version: UInt8 { get }
var type: BigUInt? { get }
func signedExtensions(using schemaResolver: Schema.Resolver) throws -> [String]
}

Expand All @@ -13,6 +14,7 @@ public protocol RuntimeExtrinsicMetadata {
extension RuntimeMetadataV1 {
public struct ExtrinsicMetadata: RuntimeExtrinsicMetadata {
public let version: UInt8
public let type: BigUInt? = nil
public let signedExtensions: [String]

public init(version: UInt8, signedExtensions: [String]) {
Expand Down Expand Up @@ -42,12 +44,13 @@ extension RuntimeMetadataV1.ExtrinsicMetadata: ScaleCodable {

extension RuntimeMetadataV14 {
public struct ExtrinsicMetadata: RuntimeExtrinsicMetadata {
public let type: BigUInt
private let _type: BigUInt
public var type: BigUInt? { _type }
public let version: UInt8
public let signedExtensions: [SignedExtension]

public init(type: BigUInt, version: UInt8, signedExtensions: [SignedExtension]) {
self.type = type
self._type = type
self.version = version
self.signedExtensions = signedExtensions
}
Expand All @@ -62,13 +65,13 @@ extension RuntimeMetadataV14 {

extension RuntimeMetadataV14.ExtrinsicMetadata: ScaleCodable {
public func encode(scaleEncoder: ScaleEncoding) throws {
try type.encode(scaleEncoder: scaleEncoder)
try _type.encode(scaleEncoder: scaleEncoder)
try version.encode(scaleEncoder: scaleEncoder)
try signedExtensions.encode(scaleEncoder: scaleEncoder)
}

public init(scaleDecoder: ScaleDecoding) throws {
type = try BigUInt(scaleDecoder: scaleDecoder)
_type = try BigUInt(scaleDecoder: scaleDecoder)
version = try UInt8(scaleDecoder: scaleDecoder)
signedExtensions = try [SignedExtension](scaleDecoder: scaleDecoder)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public class ExtrinsicSignatureNode: Node {
guard
var address = params[ExtrinsicSignature.CodingKeys.address.rawValue],
let signature = params[ExtrinsicSignature.CodingKeys.signature.rawValue],
let extra = params[ExtrinsicSignature.CodingKeys.extra.rawValue] else {
let extra = params[ExtrinsicSignature.CodingKeys.extra.rawValue],
let signatureType = params[ExtrinsicSignature.CodingKeys.type.rawValue]?.stringValue
else {
throw ExtrinsicSignatureNodeError.invalidParams
}

Expand All @@ -63,7 +65,7 @@ public class ExtrinsicSignatureNode: Node {
}

try encoder.append(json: address, type: addressType.name)
try encoder.append(json: signature, type: KnownType.signature.name)
try encoder.append(json: signature, type: signatureType)
try encoder.append(json: extra, type: GenericType.extrinsicExtra.name)
}

Expand Down
1 change: 1 addition & 0 deletions FearlessUtils/Classes/Runtime/TypeRegistry+Public.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public extension TypeRegistry {

return try TypeRegistry(
json: types,
overrides: json["overrides"]?.arrayValue,
nodeFactory: OneOfTypeNodeFactory(children: factories),
typeResolver: OneOfTypeResolver(children: resolvers),
additionalNodes: additionalNodes
Expand Down
Loading