Skip to content

Commit

Permalink
chore: 💩 Force transaction version 3
Browse files Browse the repository at this point in the history
  • Loading branch information
redDwarf03 committed Dec 30, 2024
1 parent d7986ea commit c5bf802
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- BREAKING CHANGES: Add param to `newKeychainTransaction` method to allow many services instead of only one
- BREAKING CHANGES: Add `ArchethicKeychainNotExistsException` to catch error when no keychain exists (impact on `getKeychain` method)
- Force transaction version 3

# 6.0.0-beta

Expand Down
5 changes: 3 additions & 2 deletions lib/src/model/keychain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ part 'keychain.freezed.dart';
part 'keychain.g.dart';

const int keychainOriginId = 0;
const kVersion3 = 3;

@freezed
class Keychain with _$Keychain {
const factory Keychain({
@Uint8ListConverter() Uint8List? seed,
@Default(1) final int version,
@Default(kVersion3) final int version,
@Default({}) final Map<String, Service> services,
}) = _Keychain;
const Keychain._();
Expand Down Expand Up @@ -66,7 +67,7 @@ class Keychain with _$Keychain {
});

return concatUint8List(<Uint8List>[
toByteArray(version, length: 4),
toByteArray(kVersion3, length: 4),
Uint8List.fromList(<int>[seed!.length]),
seed!,
Uint8List.fromList(<int>[services.length]),
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/keychain.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class __$$KeychainImplCopyWithImpl<$Res>
class _$KeychainImpl extends _Keychain {
const _$KeychainImpl(
{@Uint8ListConverter() this.seed,
this.version = 1,
this.version = kVersion3,
final Map<String, Service> services = const {}})
: _services = services,
super._();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/keychain.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions lib/src/model/transaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'transaction.freezed.dart';
part 'transaction.g.dart';

const int cVersion = 3;
const int kVersion = 3;

const Map<String, int> txTypes = <String, int>{
/// User based transaction types
Expand Down Expand Up @@ -95,7 +95,7 @@ class Transaction with _$Transaction {
ValidationStamp? validationStamp,

/// Version of the transaction (used for backward compatiblity)
@Default(cVersion) int version,
@Default(kVersion) int version,
}) = _Transaction;
const Transaction._();

Expand All @@ -112,7 +112,7 @@ class Transaction with _$Transaction {
/// Convert the transaction in JSON
String toNodeRPC() {
final json = jsonEncode(<String, Object?>{
'version': version,
'version': kVersion,
'address': address?.address ?? '',
'type': type,
'data': {
Expand Down Expand Up @@ -542,7 +542,7 @@ class Transaction with _$Transaction {
Uint8List.fromList(toByteArray(data!.recipients.length));

return concatUint8List(<Uint8List>[
toByteArray(version, length: 4),
toByteArray(kVersion, length: 4),
Uint8List.fromList(hexToUint8List(address!.address!)),
Uint8List.fromList(<int>[txTypes[type]!]),
bufCodeSize,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/transaction.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class _$TransactionImpl extends _Transaction {
this.previousSignature,
this.type,
this.validationStamp,
this.version = cVersion})
this.version = kVersion})
: _crossValidationStamps = crossValidationStamps,
_inputs = inputs,
super._();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/model/transaction.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 92 additions & 0 deletions test/keychain_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -524,4 +524,96 @@ void main() {
});
},
);

test(
'should create a keychain with version forced to 3',
tags: <String>[TestTags.integration],
() async {
final walletSeed = generateRandomSeed();
const endpoint = 'https://testnet.archethic.net';
final apiService = ApiService(endpoint);
final walletKeyPair = crypto.deriveKeyPair(walletSeed, 0);

/// Generate keyChain Seed from random value
final keychainSeed = uint8ListToHex(
Uint8List.fromList(
List<int>.generate(32, (int i) => Random.secure().nextInt(256)),
),
);
dev.log('keychainSeed: $keychainSeed');

/// Many services for wallet
const kServiceName1 = 'main-uco-1';
const kDerivationPathWithoutIndex1 = "m/650'/$kServiceName1/";
const index = '0';
const kDerivationPath1 = '$kDerivationPathWithoutIndex1$index';
dev.log('kDerivationPath1: $kDerivationPath1');

const kServiceName2 = 'main-uco-2';
const kDerivationPathWithoutIndex2 = "m/650'/$kServiceName2/";
const kDerivationPath2 = '$kDerivationPathWithoutIndex2$index';
dev.log('kDerivationPath2: $kDerivationPath2');

const kServiceName3 = 'main-uco-3';
const kDerivationPathWithoutIndex3 = "m/650'/$kServiceName3/";
const kDerivationPath3 = '$kDerivationPathWithoutIndex3$index';
dev.log('kDerivationPath3: $kDerivationPath3');

final originPrivateKey = apiService.getOriginKey();
dev.log('originPrivateKey: $originPrivateKey');

// We simulate version 4
const blockchainTxVersion = 4;

/// Create Keychain from keyChain seed and wallet public key to encrypt secret
final keychainTransaction = apiService.newKeychainTransaction(
keychainSeed,
<String>[
uint8ListToHex(
Uint8List.fromList(walletKeyPair.publicKey!),
),
],
Uint8List.fromList(hexToUint8List(originPrivateKey)),
blockchainTxVersion,
servicesMap: {
kServiceName1: kDerivationPath1,
kServiceName2: kDerivationPath2,
kServiceName3: kDerivationPath3,
},
);
dev.log(
'keychainTransaction: ${keychainTransaction.toNodeRPC()}',
);

/// Create Keychain Access for wallet
final accessKeychainTx = apiService.newAccessKeychainTransaction(
walletSeed,
Uint8List.fromList(
hexToUint8List(keychainTransaction.address!.address!),
),
Uint8List.fromList(hexToUint8List(originPrivateKey)),
blockchainTxVersion,
);
dev.log('accessKeychainTx: ${accessKeychainTx.toNodeRPC()}');

await ArchethicTransactionSender(
apiService: apiService,
).send(
transaction: keychainTransaction,
);

await ArchethicTransactionSender(
apiService: apiService,
).send(
transaction: accessKeychainTx,
);

/// Get KeyChain Wallet
final keychain = await apiService.getKeychain(walletSeed);

expect(keychain.services.keys.elementAt(0), 'main-uco-1');
expect(keychain.services.keys.elementAt(1), 'main-uco-2');
expect(keychain.services.keys.elementAt(2), 'main-uco-3');
},
);
}
40 changes: 40 additions & 0 deletions test/transaction_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,46 @@ condition inherit: [
transaction: tx,
);
});

test(
'sending Tx with named recipient action should work (version 4 forced)',
() async {
final apiService = ApiService('https://testnet.archethic.net');

const txChainAddress =
'00009a4e6ef5a1358db5e3406b825848b396c43ef1bde2bb0a7cc32ac9ff9512aa09';
final originPrivateKey = apiService.getOriginKey();
final lastTx = (await apiService
.getTransactionIndex([txChainAddress]))[txChainAddress] ??
0;
const text = 'Test trigger HelloWorld 001';
final tx = Transaction(
// Version 4 forced
version: 4,
type: 'data',
data: Data.fromJson(<String, dynamic>{
'code': '',
'ownerships': <Map<String, dynamic>>[],
'ledger': {
'uco': {'transfers': []},
'token': {'transfers': []},
},
}),
)
.addRecipient(
'00000E7C4C2EB7A16DA0A15811317FA828D162122AD79E1356550E5ED19CF559BF3F',
)
.setContent(text)
.build(seed, lastTx)
.transaction
.originSign(originPrivateKey);

await ArchethicTransactionSender(
apiService: apiService,
).send(
transaction: tx,
);
});
},
);
}

0 comments on commit c5bf802

Please sign in to comment.