diff --git a/DashSync.podspec b/DashSync.podspec index 96f24427e..56a15b2c0 100644 --- a/DashSync.podspec +++ b/DashSync.podspec @@ -34,7 +34,7 @@ Pod::Spec.new do |s| s.ios.framework = 'UIKit' s.macos.framework = 'Cocoa' s.compiler_flags = '-Wno-comma' - s.dependency 'DashSharedCore', '0.4.7' + s.dependency 'DashSharedCore', '0.4.8' s.dependency 'CocoaLumberjack', '3.7.2' s.ios.dependency 'DWAlertController', '0.2.1' s.dependency 'DSDynamicOptions', '0.1.2' diff --git a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m index e226fdd15..50d5b3172 100644 --- a/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSAuthenticationKeysDerivationPath.m @@ -83,7 +83,7 @@ + (instancetype)providerOwnerKeysDerivationPathForChain:(DSChain *)chain { + (instancetype)providerOperatorKeysDerivationPathForChain:(DSChain *)chain { UInt256 indexes[] = {uint256_from_long(FEATURE_PURPOSE), uint256_from_long(chain_coin_type(chain.chainType)), uint256_from_long(3), uint256_from_long(3)}; BOOL hardenedIndexes[] = {YES, YES, YES, YES}; - return [DSAuthenticationKeysDerivationPath derivationPathWithIndexes:indexes hardened:hardenedIndexes length:4 type:DSDerivationPathType_SingleUserAuthentication signingAlgorithm:[chain activeBLSType] reference:DSDerivationPathReference_ProviderOperatorKeys onChain:chain]; + return [DSAuthenticationKeysDerivationPath derivationPathWithIndexes:indexes hardened:hardenedIndexes length:4 type:DSDerivationPathType_SingleUserAuthentication signingAlgorithm:KeyKind_BLS reference:DSDerivationPathReference_ProviderOperatorKeys onChain:chain]; } + (instancetype)platformNodeKeysDerivationPathForChain:(DSChain *)chain { @@ -107,7 +107,7 @@ + (instancetype)blockchainIdentityECDSAKeysDerivationPathForChain:(DSChain *)cha + (instancetype)blockchainIdentityBLSKeysDerivationPathForChain:(DSChain *)chain { UInt256 indexes[] = {uint256_from_long(FEATURE_PURPOSE), uint256_from_long(chain_coin_type(chain.chainType)), uint256_from_long(FEATURE_PURPOSE_IDENTITIES), uint256_from_long(FEATURE_PURPOSE_IDENTITIES_SUBFEATURE_AUTHENTICATION), uint256_from_long(1)}; BOOL hardenedIndexes[] = {YES, YES, YES, YES, YES}; - DSAuthenticationKeysDerivationPath *blockchainIdentityBLSKeysDerivationPath = [DSAuthenticationKeysDerivationPath derivationPathWithIndexes:indexes hardened:hardenedIndexes length:5 type:DSDerivationPathType_MultipleUserAuthentication signingAlgorithm:[chain activeBLSType] reference:DSDerivationPathReference_BlockchainIdentities onChain:chain]; + DSAuthenticationKeysDerivationPath *blockchainIdentityBLSKeysDerivationPath = [DSAuthenticationKeysDerivationPath derivationPathWithIndexes:indexes hardened:hardenedIndexes length:5 type:DSDerivationPathType_MultipleUserAuthentication signingAlgorithm:/*[chain activeBLSType]*/KeyKind_BLS reference:DSDerivationPathReference_BlockchainIdentities onChain:chain]; blockchainIdentityBLSKeysDerivationPath.shouldStoreExtendedPrivateKey = YES; blockchainIdentityBLSKeysDerivationPath.usesHardenedKeys = YES; return blockchainIdentityBLSKeysDerivationPath; diff --git a/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m b/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m index 7a85b69ce..77d8acfb6 100644 --- a/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m +++ b/DashSync/shared/Models/Derivation Paths/DSDerivationPath.m @@ -256,19 +256,27 @@ - (NSData *)extendedPublicKeyData { return nil; } +- (void)maybeRevertBLSMigration:(NSData *)extendedPublicKeyData { + // revert + // for those who already migrated from legacy to basic BLS derivation scheme + // we revert back their extended public key to legacy + BOOL isBasicBLS = self.signingAlgorithm == KeyKind_BLSBasic; + if (isBasicBLS) { + _extendedPublicKey = key_bls_migrate_from_basic_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length); + if (_extendedPublicKey) { + setKeychainData([DSKeyManager extendedPublicKeyData:_extendedPublicKey], [self standaloneExtendedPublicKeyLocationString], NO); + } + } +} + - (OpaqueKey *)extendedPublicKey { if (!_extendedPublicKey) { if (self.wallet && (self.length || self.reference == DSDerivationPathReference_Root)) { NSData *extendedPublicKeyData = getKeychainData([self walletBasedExtendedPublicKeyLocationString], nil); if (extendedPublicKeyData) { + NoTimeLog(@"_extendedPublicKey (%d) = %@", self.signingAlgorithm, extendedPublicKeyData.hexString); _extendedPublicKey = key_create_from_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length, (int16_t) self.signingAlgorithm); - if (!_extendedPublicKey && self.signingAlgorithm == KeyKind_BLSBasic) { - // Migrate BLS key from keychain: legacy -> basic - _extendedPublicKey = key_bls_migrate_from_legacy_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length); - if (_extendedPublicKey) { - setKeychainData([DSKeyManager extendedPublicKeyData:_extendedPublicKey], [self standaloneExtendedPublicKeyLocationString], NO); - } - } + [self maybeRevertBLSMigration:extendedPublicKeyData]; NSAssert(_extendedPublicKey, @"extended public key not set"); } } else { @@ -293,11 +301,9 @@ - (OpaqueKey *)extendedPublicKey { } } #endif + NoTimeLog(@"_extendedPublicKey (%d) = %@", self.signingAlgorithm, extendedPublicKeyData.hexString); _extendedPublicKey = key_create_from_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length, (int16_t) self.signingAlgorithm); - if (!_extendedPublicKey && self.signingAlgorithm == KeyKind_BLSBasic) { - // Migrate BLS key from keychain: legacy -> basic - _extendedPublicKey = key_bls_migrate_from_legacy_extended_public_key_data(extendedPublicKeyData.bytes, extendedPublicKeyData.length); - } + [self maybeRevertBLSMigration:extendedPublicKeyData]; } } return _extendedPublicKey; diff --git a/DashSync/shared/Models/Masternode/DSLocalMasternode.m b/DashSync/shared/Models/Masternode/DSLocalMasternode.m index 8eccc738f..9edd4373d 100644 --- a/DashSync/shared/Models/Masternode/DSLocalMasternode.m +++ b/DashSync/shared/Models/Masternode/DSLocalMasternode.m @@ -492,13 +492,8 @@ - (void)registrationTransactionFundedByAccount:(DSAccount *)fundingAccount toAdd } else { operatorKey = [providerOperatorKeysDerivationPath publicKeyDataAtIndex:self.operatorWalletIndex].UInt384; } - - DSProviderRegistrationTransaction *providerRegistrationTransaction; - if ([self.chain isMainnet]) { - providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithProviderRegistrationTransactionVersion:1 type:0 mode:0 collateralOutpoint:collateral ipAddress:self.ipAddress port:self.port ownerKeyHash:ownerKeyHash operatorKey:operatorKey votingKeyHash:votingKeyHash platformNodeID:UINT160_ZERO operatorReward:0 scriptPayout:script onChain:fundingAccount.wallet.chain]; - } else { - providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithProviderRegistrationTransactionVersion:2 type:0 mode:0 collateralOutpoint:collateral ipAddress:self.ipAddress port:self.port ownerKeyHash:ownerKeyHash operatorKey:operatorKey votingKeyHash:votingKeyHash platformNodeID:platformNodeID operatorReward:0 scriptPayout:script onChain:fundingAccount.wallet.chain]; - } + uint16_t operatorKeyVersion = providerOperatorKeysDerivationPath.signingAlgorithm == KeyKind_BLS ? 1 : 2; + DSProviderRegistrationTransaction *providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithProviderRegistrationTransactionVersion:2 type:0 mode:0 collateralOutpoint:collateral ipAddress:self.ipAddress port:self.port ownerKeyHash:ownerKeyHash operatorKey:operatorKey operatorKeyVersion:operatorKeyVersion votingKeyHash:votingKeyHash platformNodeID:platformNodeID operatorReward:0 scriptPayout:script onChain:fundingAccount.wallet.chain]; if (dsutxo_is_zero(collateral)) { NSString *holdingAddress = [providerFundsDerivationPath receiveAddress]; NSData *scriptPayout = [DSKeyManager scriptPubKeyForAddress:holdingAddress forChain:self.holdingKeysWallet.chain]; diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.h b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.h index 0c358b2f3..8e09c8c4f 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.h +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.h @@ -46,9 +46,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) UInt160 platformNodeID; @property (nullable, nonatomic, readonly) NSString *platformNodeAddress; -- (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)indexes inputScripts:(NSArray *)scripts inputSequences:(NSArray *)inputSequences outputAddresses:(NSArray *)addresses outputAmounts:(NSArray *)amounts providerRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey votingKeyHash:(UInt160)votingKeyHash operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain; +- (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)indexes inputScripts:(NSArray *)scripts inputSequences:(NSArray *)inputSequences outputAddresses:(NSArray *)addresses outputAmounts:(NSArray *)amounts providerRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey operatorKeyVersion:(uint16_t)operatorKeyVersion votingKeyHash:(UInt160)votingKeyHash operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain; -- (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey votingKeyHash:(UInt160)votingKeyHash platformNodeID:(UInt160)platformNodeID operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain; +- (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey operatorKeyVersion:(uint16_t)operatorKeyVersion votingKeyHash:(UInt160)votingKeyHash platformNodeID:(UInt160)platformNodeID operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain; - (void)updateInputsHash; diff --git a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m index df31b83fc..a0bc90e2f 100644 --- a/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m +++ b/DashSync/shared/Models/Transactions/Provider/DSProviderRegistrationTransaction.m @@ -119,7 +119,7 @@ - (instancetype)initWithMessage:(NSData *)message onChain:(DSChain *)chain { } -- (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey votingKeyHash:(UInt160)votingKeyHash platformNodeID:(UInt160)platformNodeID operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain { +- (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey operatorKeyVersion:(uint16_t)operatorKeyVersion votingKeyHash:(UInt160)votingKeyHash platformNodeID:(UInt160)platformNodeID operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *)chain { NSParameterAssert(scriptPayout); NSParameterAssert(chain); @@ -134,6 +134,7 @@ - (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version self.port = port; self.ownerKeyHash = ownerKeyHash; self.operatorKey = operatorKey; + self.operatorKeyVersion = operatorKeyVersion; self.votingKeyHash = votingKeyHash; self.platformNodeID = platformNodeID; self.operatorReward = operatorReward; @@ -142,7 +143,7 @@ - (instancetype)initWithProviderRegistrationTransactionVersion:(uint16_t)version return self; } -- (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)indexes inputScripts:(NSArray *)scripts inputSequences:(NSArray *)inputSequences outputAddresses:(NSArray *)addresses outputAmounts:(NSArray *)amounts providerRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey votingKeyHash:(UInt160)votingKeyHash operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *_Nonnull)chain { +- (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)indexes inputScripts:(NSArray *)scripts inputSequences:(NSArray *)inputSequences outputAddresses:(NSArray *)addresses outputAmounts:(NSArray *)amounts providerRegistrationTransactionVersion:(uint16_t)version type:(uint16_t)providerType mode:(uint16_t)providerMode collateralOutpoint:(DSUTXO)collateralOutpoint ipAddress:(UInt128)ipAddress port:(uint16_t)port ownerKeyHash:(UInt160)ownerKeyHash operatorKey:(UInt384)operatorKey operatorKeyVersion:(uint16_t)operatorKeyVersion votingKeyHash:(UInt160)votingKeyHash operatorReward:(uint16_t)operatorReward scriptPayout:(NSData *)scriptPayout onChain:(DSChain *_Nonnull)chain { NSParameterAssert(hashes); NSParameterAssert(indexes); NSParameterAssert(scripts); @@ -163,6 +164,7 @@ - (instancetype)initWithInputHashes:(NSArray *)hashes inputIndexes:(NSArray *)in self.port = port; self.ownerKeyHash = ownerKeyHash; self.operatorKey = operatorKey; + self.operatorKeyVersion = operatorKeyVersion; self.votingKeyHash = votingKeyHash; self.operatorReward = operatorReward; self.scriptPayout = scriptPayout; diff --git a/Example/Podfile b/Example/Podfile index a6f01f405..e9ea92bcd 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,5 +1,5 @@ def common_pods -# pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :branch => 'fix/bls-bindings' +# pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :branch => 'fix/revert-bls-legacy-scheme-derivation' # pod 'DashSharedCore', :git => 'https://github.com/dashpay/dash-shared-core.git', :commit => '27157c7' pod 'DashSync', :path => '../' pod 'SDWebImage', '5.14.3' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 5e20a73cc..0b55243e2 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -586,11 +586,11 @@ PODS: - "!ProtoCompiler-gRPCPlugin (~> 1.0)" - DAPI-GRPC/Messages - gRPC-ProtoRPC - - DashSharedCore (0.4.7) + - DashSharedCore (0.4.8) - DashSync (0.1.0): - CocoaLumberjack (= 3.7.2) - DAPI-GRPC (= 0.22.0-dev.8) - - DashSharedCore (= 0.4.7) + - DashSharedCore (= 0.4.8) - DSDynamicOptions (= 0.1.2) - DWAlertController (= 0.2.1) - TinyCborObjc (= 0.4.6) @@ -712,8 +712,8 @@ SPEC CHECKSUMS: CocoaImageHashing: 8656031d0899abe6c1c415827de43e9798189c53 CocoaLumberjack: b7e05132ff94f6ae4dfa9d5bce9141893a21d9da DAPI-GRPC: 138d62523bbfe7e88a39896f1053c0bc12390d9f - DashSharedCore: c33567249c4bf4166609d828e5b45cacf41b784c - DashSync: bc3998e01da4f74bfb8fc9d4637d8a291704a8a9 + DashSharedCore: cc87193cfc09b816c5f472b50174cc76e41668b1 + DashSync: d53609a65e3965d246f68244883062093c0bbee6 DSDynamicOptions: 347cc5d2c4e080eb3de6a86719ad3d861b82adfc DWAlertController: 5f4cd8adf90336331c054857f709f5f8d4b16a5b gRPC: 64f36d689b2ecd99c4351f74e6f91347cdc65d9f @@ -726,6 +726,6 @@ SPEC CHECKSUMS: tinycbor: d4d71dddda1f8392fbb4249f63faf8552f327590 TinyCborObjc: 5204540fb90ff0c40fb22d408fa51bab79d78a80 -PODFILE CHECKSUM: 4a6ed5ed41963191295a38fad9760424b46ae9a9 +PODFILE CHECKSUM: 65ee9c6b1d7ae6ab3bc40337f53a5135ff99a2f1 COCOAPODS: 1.12.1 diff --git a/Example/Tests/DSProviderTransactionsTests.m b/Example/Tests/DSProviderTransactionsTests.m index 7d331739c..60369bb44 100644 --- a/Example/Tests/DSProviderTransactionsTests.m +++ b/Example/Tests/DSProviderTransactionsTests.m @@ -148,6 +148,7 @@ - (void)testCollateralProviderRegistrationTransaction { OpaqueKey *ownerKey = [providerOwnerKeysDerivationPath privateKeyAtIndex:0 fromSeed:seed]; UInt160 votingKeyHash = [providerVotingKeysDerivationPath publicKeyDataAtIndex:0].hash160; UInt384 operatorKey = [providerOperatorKeysDerivationPath publicKeyDataAtIndex:0].UInt384; + uint16_t operatorKeyVersion = 1; // BLS legacy NSData *scriptPayout = [DSKeyManager scriptPubKeyForAddress:payoutAddress forChain:chain]; UInt128 ipAddress = {.u32 = {0, 0, CFSwapInt32HostToBig(0xffff), 0}}; @@ -159,7 +160,7 @@ - (void)testCollateralProviderRegistrationTransaction { NSData *inputScript = [DSKeyManager scriptPubKeyForAddress:inputAddress0 forChain:chain]; - DSProviderRegistrationTransaction *providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithInputHashes:@[inputTransactionHashValue] inputIndexes:@[@1] inputScripts:@[inputScript] inputSequences:@[@(TXIN_SEQUENCE)] outputAddresses:@[outputAddress0] outputAmounts:@[@40777037710] providerRegistrationTransactionVersion:1 type:0 mode:0 collateralOutpoint:reversedCollateral ipAddress:ipAddress port:19999 ownerKeyHash:[DSKeyManager publicKeyData:ownerKey].hash160 operatorKey:operatorKey votingKeyHash:votingKeyHash operatorReward:0 scriptPayout:scriptPayout onChain:chain]; + DSProviderRegistrationTransaction *providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithInputHashes:@[inputTransactionHashValue] inputIndexes:@[@1] inputScripts:@[inputScript] inputSequences:@[@(TXIN_SEQUENCE)] outputAddresses:@[outputAddress0] outputAmounts:@[@40777037710] providerRegistrationTransactionVersion:1 type:0 mode:0 collateralOutpoint:reversedCollateral ipAddress:ipAddress port:19999 ownerKeyHash:[DSKeyManager publicKeyData:ownerKey].hash160 operatorKey:operatorKey operatorKeyVersion:operatorKeyVersion votingKeyHash:votingKeyHash operatorReward:0 scriptPayout:scriptPayout onChain:chain]; providerRegistrationTransaction.payloadSignature = signatureData; @@ -242,6 +243,7 @@ - (void)testNoCollateralProviderRegistrationTransaction { UInt160 votingKeyHash = [providerVotingKeysDerivationPath publicKeyDataAtIndex:0].hash160; UInt384 operatorKey = [providerOperatorKeysDerivationPath publicKeyDataAtIndex:0].UInt384; + uint16_t operatorKeyVersion = 1; // BLS legacy DSProviderRegistrationTransaction *providerRegistrationTransactionFromMessage = [[DSProviderRegistrationTransaction alloc] initWithMessage:hexData onChain:chain]; XCTAssertEqualObjects(providerRegistrationTransactionFromMessage.toData, hexData, @"Provider transaction does not match it's data"); @@ -263,7 +265,7 @@ - (void)testNoCollateralProviderRegistrationTransaction { [DSKeyManager scriptPubKeyForAddress:inputAddress2 forChain:chain] ]; - DSProviderRegistrationTransaction *providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithInputHashes:inputHashes inputIndexes:inputIndexes inputScripts:inputScripts inputSequences:@[@(TXIN_SEQUENCE), @(TXIN_SEQUENCE), @(TXIN_SEQUENCE)] outputAddresses:@[outputAddress0, outputAddress1] outputAmounts:@[@100000000000, @10110995523] providerRegistrationTransactionVersion:1 type:0 mode:0 collateralOutpoint:DSUTXO_ZERO ipAddress:ipAddress port:19999 ownerKeyHash:[DSKeyManager publicKeyData:ownerKey].hash160 operatorKey:operatorKey votingKeyHash:votingKeyHash operatorReward:0 scriptPayout:scriptPayout onChain:wallet.chain]; + DSProviderRegistrationTransaction *providerRegistrationTransaction = [[DSProviderRegistrationTransaction alloc] initWithInputHashes:inputHashes inputIndexes:inputIndexes inputScripts:inputScripts inputSequences:@[@(TXIN_SEQUENCE), @(TXIN_SEQUENCE), @(TXIN_SEQUENCE)] outputAddresses:@[outputAddress0, outputAddress1] outputAmounts:@[@100000000000, @10110995523] providerRegistrationTransactionVersion:1 type:0 mode:0 collateralOutpoint:DSUTXO_ZERO ipAddress:ipAddress port:19999 ownerKeyHash:[DSKeyManager publicKeyData:ownerKey].hash160 operatorKey:operatorKey operatorKeyVersion:operatorKeyVersion votingKeyHash:votingKeyHash operatorReward:0 scriptPayout:scriptPayout onChain:wallet.chain]; [providerRegistrationTransaction updateInputsHash];