From 0cd862d8f4bda293ea383c662e03433285eaa281 Mon Sep 17 00:00:00 2001 From: parodyBit Date: Mon, 11 Dec 2023 20:42:07 -0700 Subject: [PATCH 1/4] feat: add stake integration schema --- example/stake_transaction_example.dart | 62 ++++++++++++ lib/constants.dart | 5 +- lib/src/constants.dart | 3 + lib/src/schema/schema.dart | 9 +- lib/src/schema/stake_body.dart | 113 ++++++++++++++++++++++ lib/src/schema/stake_output.dart | 81 ++++++++++++++++ lib/src/schema/stake_transaction.dart | 89 +++++++++++++++++ lib/src/schema/unstake_body.dart | 122 ++++++++++++++++++++++++ lib/src/schema/unstake_transaction.dart | 89 +++++++++++++++++ 9 files changed, 571 insertions(+), 2 deletions(-) create mode 100644 example/stake_transaction_example.dart create mode 100644 lib/src/schema/stake_body.dart create mode 100644 lib/src/schema/stake_output.dart create mode 100644 lib/src/schema/stake_transaction.dart create mode 100644 lib/src/schema/unstake_body.dart create mode 100644 lib/src/schema/unstake_transaction.dart diff --git a/example/stake_transaction_example.dart b/example/stake_transaction_example.dart new file mode 100644 index 0000000..3aa4f6f --- /dev/null +++ b/example/stake_transaction_example.dart @@ -0,0 +1,62 @@ +// import 'package:witnet/node.dart'; +import 'package:witnet/schema.dart'; +import 'package:witnet/src/constants.dart'; +import 'package:witnet/src/utils/transformations/transformations.dart'; +import 'package:witnet/witnet.dart'; + +var outputPointer = OutputPointer.fromString( + '0000000000000000000000000000000000000000000000000000000000000000:0'); + +void main() async { + /// connect to local node rpc + // NodeClient nodeClient = NodeClient(address: "127.0.0.1", port: 21338); + + // String mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + /// load node xprv for the default mnemonic + Xprv masterNode = Xprv.fromXprv( + "xprv1qpujxsyd4hfu0dtwa524vac84e09mjsgnh5h9crl8wrqg58z5wmsuqqcxlqmar3fjhkprndzkpnp2xlze76g4hu7g7c4r4r2m2e6y8xlvu566tn6"); + + Xprv withdrawer = masterNode / + KEYPATH_PURPOSE / + KEYPATH_COIN_TYPE / + KEYPATH_ACCOUNT / + EXTERNAL_KEYCHAIN / + 0; + + /// The 20 byte Public Key Hash of the withdrawer + String pkh = bytesToHex(withdrawer.privateKey.publicKey.publicKeyHash); + + /// The authorization by the node + KeyedSignature authorization = signHash(pkh, masterNode.privateKey); + + /// build stake transaction body + StakeBody body = StakeBody( + inputs: [ + Input(outputPointer: outputPointer), + ], + output: StakeOutput( + value: MINIMUM_STAKEABLE_AMOUNT_WITS, + authorization: authorization, + ), + ); + + /// build and sign stake transaction + StakeTransaction stake = StakeTransaction( + body: body, + signatures: [signHash(body.transactionId, masterNode.privateKey)]); + + /// The Stake Transaction ID + print(stake.transactionID); + + /// send stake transaction + /// var response = await nodeClient.inventory(stake.jsonMap()); +} + +/// Sign Hash +KeyedSignature signHash(String hash, WitPrivateKey privateKey) { + final sig = privateKey.signature(hash); + return KeyedSignature( + publicKey: PublicKey(bytes: privateKey.publicKey.encode()), + signature: Signature(secp256k1: Secp256k1Signature(der: sig.encode())), + ); +} diff --git a/lib/constants.dart b/lib/constants.dart index a8cfdc0..8bdd107 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -12,4 +12,7 @@ export 'src/constants.dart' KEYPATH_PURPOSE, KEYPATH_COIN_TYPE, EXTERNAL_KEYCHAIN, - INTERNAL_KEYCHAIN; + INTERNAL_KEYCHAIN, + STAKE_OUTPUT_WEIGHT, + UNSTAKE_OUTPUT_WEIGHT, + MINIMUM_STAKEABLE_AMOUNT_WITS; diff --git a/lib/src/constants.dart b/lib/src/constants.dart index d0b8be0..1a10d62 100644 --- a/lib/src/constants.dart +++ b/lib/src/constants.dart @@ -1,5 +1,8 @@ const INPUT_SIZE = 133; const OUTPUT_SIZE = 36; +const STAKE_OUTPUT_WEIGHT = 105; +const UNSTAKE_OUTPUT_WEIGHT = 153; +const MINIMUM_STAKEABLE_AMOUNT_WITS = 10000; const COMMIT_WEIGHT = 400; const REVEAL_WEIGHT = 200; const TALLY_WEIGHT = 100; diff --git a/lib/src/schema/schema.dart b/lib/src/schema/schema.dart index a904830..8993cf0 100644 --- a/lib/src/schema/schema.dart +++ b/lib/src/schema/schema.dart @@ -16,7 +16,9 @@ import 'package:witnet/constants.dart' REVEAL_WEIGHT, TALLY_WEIGHT, INPUT_SIZE, - OUTPUT_SIZE; + OUTPUT_SIZE, + STAKE_OUTPUT_WEIGHT, + UNSTAKE_OUTPUT_WEIGHT; import '../../radon.dart' show radToCbor, cborToRad; @@ -54,6 +56,11 @@ part 'reveal_body.dart'; part 'reveal_transaction.dart'; part 'secp256k1_signature.dart'; part 'signature.dart'; +part 'stake_body.dart'; +part 'stake_output.dart'; +part 'stake_transaction.dart'; +part 'unstake_body.dart'; +part 'unstake_transaction.dart'; part 'string_pair.dart'; part 'super_block.dart'; part 'super_block_vote.dart'; diff --git a/lib/src/schema/stake_body.dart b/lib/src/schema/stake_body.dart new file mode 100644 index 0000000..3f7ed41 --- /dev/null +++ b/lib/src/schema/stake_body.dart @@ -0,0 +1,113 @@ +part of 'schema.dart'; + +class StakeBody extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('StakeBody', + package: const PackageName('witnet'), createEmptyInstance: create) + ..pc(1, 'inputs', PbFieldType.PM, subBuilder: Input.create) + ..aOM(2, 'output', subBuilder: StakeOutput.create) + ..aOM(2, 'change', + subBuilder: ValueTransferOutput.create) + ..hasRequiredFields = false; + + static StakeBody create() => StakeBody._(); + static PbList createRepeated() => PbList(); + static StakeBody getDefault() => + _defaultInstance ??= GeneratedMessage.$_defaultFor(create); + static StakeBody? _defaultInstance; + + StakeBody._() : super(); + + @override + StakeBody clone() => StakeBody()..mergeFromMessage(this); + + @override + StakeBody createEmptyInstance() => create(); + + factory StakeBody({ + Iterable? inputs, + StakeOutput? output, + ValueTransferOutput? change, + }) { + final _result = create(); + if (inputs != null) { + _result.inputs.addAll(inputs); + } + if (output != null) { + _result.output = output; + } + if (change != null) { + _result.change = change; + } + return _result; + } + + factory StakeBody.fromRawJson(String str) => + StakeBody.fromJson(json.decode(str)); + + @override + factory StakeBody.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + + @override + factory StakeBody.fromJson(Map json) => StakeBody( + inputs: List.from(json["inputs"].map((x) => Input.fromJson(x))), + output: StakeOutput.fromJson(json["output"]), + change: ValueTransferOutput.fromJson(json["change"]), + ); + + factory StakeBody.fromPbBytes(Uint8List buffer) => + create()..mergeFromBuffer(buffer, ExtensionRegistry.EMPTY); + + String toRawJson({bool asHex = false}) => json.encode(jsonMap(asHex: asHex)); + + Map jsonMap({bool asHex = false}) => { + "inputs": + List.from(inputs.map((x) => x.jsonMap(asHex: asHex))), + "output": output.jsonMap(asHex: asHex), + "change": change.jsonMap(asHex: asHex), + }; + + Uint8List get pbBytes => writeToBuffer(); + + Uint8List get hash => sha256(data: pbBytes); + + String get transactionId => bytesToHex(hash); + // VT_weight = N * INPUT_SIZE + M * OUTPUT_SIZE + STAKE_OUTPUT_WEIGHT + int get weight => + (inputs.length * INPUT_SIZE) + OUTPUT_SIZE + STAKE_OUTPUT_WEIGHT; + + @override + BuilderInfo get info_ => _i; + + @TagNumber(1) + List get inputs => $_getList(0); + + @TagNumber(2) + StakeOutput get output => $_getN(1); + @TagNumber(2) + set output(StakeOutput v) { + setField(2, v); + } + + @TagNumber(2) + bool hasOutput() => $_has(1); + @TagNumber(2) + void clearOutput() => clearField(2); + @TagNumber(2) + StakeOutput ensureOutput() => $_ensure(1); + + @TagNumber(3) + ValueTransferOutput get change => $_getN(2); + @TagNumber(3) + set change(ValueTransferOutput v) { + setField(3, v); + } + + @TagNumber(3) + bool hasChange() => $_has(2); + @TagNumber(3) + void clearChange() => clearField(3); + @TagNumber(3) + VTTransactionBody ensureChange() => $_ensure(2); +} diff --git a/lib/src/schema/stake_output.dart b/lib/src/schema/stake_output.dart new file mode 100644 index 0000000..f1ecd31 --- /dev/null +++ b/lib/src/schema/stake_output.dart @@ -0,0 +1,81 @@ +part of 'schema.dart'; + +class StakeOutput extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('StakeOutput', + package: const PackageName('witnet'), createEmptyInstance: create) + ..a(1, 'value', PbFieldType.OU6, defaultOrMaker: Int64.ZERO) + ..aOM(2, 'authorization', subBuilder: KeyedSignature.create) + ..hasRequiredFields = false; + + static StakeOutput create() => StakeOutput._(); + static PbList createRepeated() => PbList(); + static StakeOutput getDefault() => + _defaultInstance ??= GeneratedMessage.$_defaultFor(create); + static StakeOutput? _defaultInstance; + StakeOutput._() : super(); + + @override + GeneratedMessage clone() => StakeOutput()..mergeFromMessage(this); + + @override + GeneratedMessage createEmptyInstance() => create(); + + factory StakeOutput({ + int? value, + KeyedSignature? authorization, + }) { + final _result = create(); + if (value != null) { + _result.value = Int64(value); + } + if (authorization != null) { + _result.authorization = authorization; + } + return _result; + } + + factory StakeOutput.fromRawJson(String str) => + StakeOutput.fromJson(json.decode(str)); + + @override + factory StakeOutput.fromJson(Map json) => StakeOutput( + value: json["value"], + authorization: KeyedSignature.fromJson(json["authorization"]), + ); + + Map jsonMap({bool asHex = false}) => { + "value": value.toInt(), + "authorization": authorization.jsonMap(asHex: asHex), + }; + + @override + BuilderInfo get info_ => _i; + + Uint8List get pbBytes => writeToBuffer(); + + @TagNumber(1) + Int64 get value => $_getI64(1); + @TagNumber(1) + set value(Int64 v) { + $_setInt64(0, v); + } + + @TagNumber(1) + bool hasValue() => $_has(0); + @TagNumber(1) + void clearValue() => clearField(1); + + @TagNumber(2) + KeyedSignature get authorization => $_getN(2); + @TagNumber(2) + set authorization(KeyedSignature v) { + setField(2, v); + } + + @TagNumber(2) + bool hasAuthorization() => $_has(1); + @TagNumber(2) + void clearAuthorization() => clearField(2); + @TagNumber(2) + PublicKeyHash ensureAuthorization() => $_ensure(1); +} diff --git a/lib/src/schema/stake_transaction.dart b/lib/src/schema/stake_transaction.dart new file mode 100644 index 0000000..6b80ff8 --- /dev/null +++ b/lib/src/schema/stake_transaction.dart @@ -0,0 +1,89 @@ +part of 'schema.dart'; + +class StakeTransaction extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('StakeTransaction', + package: const PackageName('witnet'), createEmptyInstance: create) + ..aOM(1, 'body', subBuilder: StakeBody.create) + ..pc(2, 'signatures', PbFieldType.PM, + subBuilder: KeyedSignature.create) + ..hasRequiredFields = false; + + static StakeTransaction create() => StakeTransaction._(); + static PbList createRepeated() => + PbList(); + static StakeTransaction getDefault() => _defaultInstance ??= + GeneratedMessage.$_defaultFor(create); + static StakeTransaction? _defaultInstance; + + StakeTransaction._() : super(); + + @override + StakeTransaction clone() => StakeTransaction()..mergeFromMessage(this); + + @override + StakeTransaction createEmptyInstance() => create(); + + factory StakeTransaction({ + StakeBody? body, + Iterable? signatures, + }) { + final _result = create(); + if (body != null) { + _result.body = body; + } + if (signatures != null) { + _result.signatures.addAll(signatures); + } + return _result; + } + + factory StakeTransaction.fromRawJson(String str) => + StakeTransaction.fromJson(json.decode(str)); + + @override + factory StakeTransaction.fromJson(Map json) => + StakeTransaction( + body: StakeBody.fromJson(json["body"]), + signatures: List.from( + json["signatures"].map((x) => KeyedSignature.fromJson(x))), + ); + + @override + factory StakeTransaction.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + + String rawJson({bool asHex = false}) => json.encode(jsonMap(asHex: asHex)); + + Map jsonMap({bool asHex = false}) => { + "body": body.jsonMap(asHex: asHex), + "signatures": + List.from(signatures.map((x) => x.jsonMap(asHex: asHex))), + }; + + String get transactionID => bytesToHex(body.hash); + + int get weight => body.weight; + + @override + BuilderInfo get info_ => _i; + + Uint8List get pbBytes => writeToBuffer(); + + @TagNumber(1) + StakeBody get body => $_getN(0); + @TagNumber(1) + set body(StakeBody v) { + setField(1, v); + } + + @TagNumber(1) + bool hasBody() => $_has(0); + @TagNumber(1) + void clearBody() => clearField(1); + @TagNumber(1) + StakeBody ensureBody() => $_ensure(0); + + @TagNumber(2) + List get signatures => $_getList(1); +} diff --git a/lib/src/schema/unstake_body.dart b/lib/src/schema/unstake_body.dart new file mode 100644 index 0000000..00bcf62 --- /dev/null +++ b/lib/src/schema/unstake_body.dart @@ -0,0 +1,122 @@ +part of 'schema.dart'; + +class UnstakeBody extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('UnstakeBody', + package: const PackageName('witnet'), createEmptyInstance: create) + ..aOM(1, 'operator', subBuilder: PublicKeyHash.create) + ..aOM(2, 'withdrawal', + subBuilder: ValueTransferOutput.create) + ..aOM(2, 'change', + subBuilder: ValueTransferOutput.create) + ..hasRequiredFields = false; + + static UnstakeBody create() => UnstakeBody._(); + static PbList createRepeated() => PbList(); + static UnstakeBody getDefault() => + _defaultInstance ??= GeneratedMessage.$_defaultFor(create); + static UnstakeBody? _defaultInstance; + + UnstakeBody._() : super(); + + @override + UnstakeBody clone() => UnstakeBody()..mergeFromMessage(this); + + @override + UnstakeBody createEmptyInstance() => create(); + + factory UnstakeBody({ + PublicKeyHash? operator, + ValueTransferOutput? withdrawal, + ValueTransferOutput? change, + }) { + final _result = create(); + if (operator != null) { + _result.operator = operator; + } + if (withdrawal != null) { + _result.withdrawal = withdrawal; + } + if (change != null) { + _result.change = change; + } + return _result; + } + + factory UnstakeBody.fromRawJson(String str) => + UnstakeBody.fromJson(json.decode(str)); + + @override + factory UnstakeBody.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + + @override + factory UnstakeBody.fromJson(Map json) => UnstakeBody( + operator: PublicKeyHash.fromAddress(json["operator"]), + withdrawal: ValueTransferOutput.fromJson(json["withdrawal"]), + change: ValueTransferOutput.fromJson(json["change"]), + ); + + factory UnstakeBody.fromPbBytes(Uint8List buffer) => + create()..mergeFromBuffer(buffer, ExtensionRegistry.EMPTY); + + String toRawJson({bool asHex = false}) => json.encode(jsonMap(asHex: asHex)); + + Map jsonMap({bool asHex = false}) => { + "operator": operator.address, + "withdrawal": withdrawal.jsonMap(asHex: asHex), + "change": change.jsonMap(asHex: asHex), + }; + + Uint8List get pbBytes => writeToBuffer(); + + Uint8List get hash => sha256(data: pbBytes); + + // VT_weight = 153 + int get weight => UNSTAKE_OUTPUT_WEIGHT; + + @override + BuilderInfo get info_ => _i; + + @TagNumber(1) + PublicKeyHash get operator => $_getN(0); + @TagNumber(1) + set operator(PublicKeyHash v) { + setField(1, v); + } + + @TagNumber(1) + bool hasOperator() => $_has(0); + @TagNumber(1) + void clearOperator() => clearField(1); + @TagNumber(1) + PublicKeyHash ensureOperator() => $_ensure(0); + + @TagNumber(2) + ValueTransferOutput get withdrawal => $_getN(1); + @TagNumber(2) + set withdrawal(ValueTransferOutput v) { + setField(2, v); + } + + @TagNumber(2) + bool hasWithdrawal() => $_has(1); + @TagNumber(2) + void clearWithdrawal() => clearField(2); + @TagNumber(2) + ValueTransferOutput ensureWithdrawal() => $_ensure(1); + + @TagNumber(3) + ValueTransferOutput get change => $_getN(2); + @TagNumber(3) + set change(ValueTransferOutput v) { + setField(3, v); + } + + @TagNumber(3) + bool hasChange() => $_has(2); + @TagNumber(3) + void clearChange() => clearField(3); + @TagNumber(3) + ValueTransferOutput ensureChange() => $_ensure(2); +} diff --git a/lib/src/schema/unstake_transaction.dart b/lib/src/schema/unstake_transaction.dart new file mode 100644 index 0000000..eec33db --- /dev/null +++ b/lib/src/schema/unstake_transaction.dart @@ -0,0 +1,89 @@ +part of 'schema.dart'; + +class UnstakeTransaction extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('UnstakeTransaction', + package: const PackageName('witnet'), createEmptyInstance: create) + ..aOM(1, 'body', subBuilder: UnstakeBody.create) + ..pc(2, 'signatures', PbFieldType.PM, + subBuilder: KeyedSignature.create) + ..hasRequiredFields = false; + + static UnstakeTransaction create() => UnstakeTransaction._(); + static PbList createRepeated() => + PbList(); + static UnstakeTransaction getDefault() => _defaultInstance ??= + GeneratedMessage.$_defaultFor(create); + static UnstakeTransaction? _defaultInstance; + + UnstakeTransaction._() : super(); + + @override + UnstakeTransaction clone() => UnstakeTransaction()..mergeFromMessage(this); + + @override + UnstakeTransaction createEmptyInstance() => create(); + + factory UnstakeTransaction({ + UnstakeBody? body, + Iterable? signatures, + }) { + final _result = create(); + if (body != null) { + _result.body = body; + } + if (signatures != null) { + _result.signatures.addAll(signatures); + } + return _result; + } + + factory UnstakeTransaction.fromRawJson(String str) => + UnstakeTransaction.fromJson(json.decode(str)); + + @override + factory UnstakeTransaction.fromJson(Map json) => + UnstakeTransaction( + body: UnstakeBody.fromJson(json["body"]), + signatures: List.from( + json["signatures"].map((x) => KeyedSignature.fromJson(x))), + ); + + @override + factory UnstakeTransaction.fromBuffer(List i, + [ExtensionRegistry r = ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + + String rawJson({bool asHex = false}) => json.encode(jsonMap(asHex: asHex)); + + Map jsonMap({bool asHex = false}) => { + "body": body.jsonMap(asHex: asHex), + "signatures": + List.from(signatures.map((x) => x.jsonMap(asHex: asHex))), + }; + + String get transactionID => bytesToHex(body.hash); + + int get weight => body.weight; + + @override + BuilderInfo get info_ => _i; + + Uint8List get pbBytes => writeToBuffer(); + + @TagNumber(1) + UnstakeBody get body => $_getN(0); + @TagNumber(1) + set body(UnstakeBody v) { + setField(1, v); + } + + @TagNumber(1) + bool hasBody() => $_has(0); + @TagNumber(1) + void clearBody() => clearField(1); + @TagNumber(1) + UnstakeBody ensureBody() => $_ensure(0); + + @TagNumber(2) + List get signatures => $_getList(1); +} From 30ed84432464a20b5832dbafaba6b684cbd7ba56 Mon Sep 17 00:00:00 2001 From: parodyBit <58690522+parodyBit@users.noreply.github.com> Date: Fri, 17 May 2024 07:04:36 -0600 Subject: [PATCH 2/4] feat: update staking schema --- example/stake_transaction_example.dart | 11 ++++ lib/src/schema/schema.dart | 1 + lib/src/schema/stake_key.dart | 84 +++++++++++++++++++++++++ lib/src/schema/stake_output.dart | 38 +++++++++-- lib/src/schema/unstake_body.dart | 23 +------ lib/src/schema/unstake_transaction.dart | 33 +++++++--- 6 files changed, 154 insertions(+), 36 deletions(-) create mode 100644 lib/src/schema/stake_key.dart diff --git a/example/stake_transaction_example.dart b/example/stake_transaction_example.dart index 3aa4f6f..fde8700 100644 --- a/example/stake_transaction_example.dart +++ b/example/stake_transaction_example.dart @@ -50,6 +50,17 @@ void main() async { /// send stake transaction /// var response = await nodeClient.inventory(stake.jsonMap()); + /// + UnstakeBody unstakeBody = UnstakeBody( + operator: PublicKeyHash.fromAddress(""), + withdrawal: ValueTransferOutput.fromJson({})); + + KeyedSignature unstakeSignature = + signHash(bytesToHex(unstakeBody.hash), masterNode.privateKey); + UnstakeTransaction unstake = + UnstakeTransaction(body: unstakeBody, signature: unstakeSignature); + + print(unstake.transactionID); } /// Sign Hash diff --git a/lib/src/schema/schema.dart b/lib/src/schema/schema.dart index 8993cf0..c3486bd 100644 --- a/lib/src/schema/schema.dart +++ b/lib/src/schema/schema.dart @@ -57,6 +57,7 @@ part 'reveal_transaction.dart'; part 'secp256k1_signature.dart'; part 'signature.dart'; part 'stake_body.dart'; +part 'stake_key.dart'; part 'stake_output.dart'; part 'stake_transaction.dart'; part 'unstake_body.dart'; diff --git a/lib/src/schema/stake_key.dart b/lib/src/schema/stake_key.dart new file mode 100644 index 0000000..850877c --- /dev/null +++ b/lib/src/schema/stake_key.dart @@ -0,0 +1,84 @@ +part of 'schema.dart'; + + +class StakeKey extends GeneratedMessage { + static final BuilderInfo _i = BuilderInfo('StakeOutput', + package: const PackageName('witnet'), createEmptyInstance: create) + ..aOM(1, 'validator', subBuilder: PublicKeyHash.create) + ..aOM(2, 'withdrawer', subBuilder: PublicKeyHash.create) + ..hasRequiredFields = false; + + static StakeKey create() => StakeKey._(); + static PbList createRepeated() => PbList(); + static StakeKey getDefault() => + _defaultInstance ??= GeneratedMessage.$_defaultFor(create); + static StakeKey? _defaultInstance; + StakeKey._() : super(); + + @override + GeneratedMessage clone() => StakeKey()..mergeFromMessage(this); + + @override + GeneratedMessage createEmptyInstance() => create(); + + factory StakeKey({ + PublicKeyHash? validator, + PublicKeyHash? withdrawer, + }) { + final _result = create(); + if (validator != null) { + _result.validator = validator; + } + if (withdrawer != null) { + _result.withdrawer = withdrawer; + } + return _result; + } + + factory StakeKey.fromRawJson(String str) => + StakeKey.fromJson(json.decode(str)); + + @override + factory StakeKey.fromJson(Map json) => StakeKey( + validator: PublicKeyHash.fromAddress(json["validator"]), + withdrawer: PublicKeyHash.fromAddress(json["withdrawer"]), + ); + + Map jsonMap({bool asHex = false}) => { + "validator": validator.address, + "withdrawer": withdrawer.address, + }; + + @override + BuilderInfo get info_ => _i; + + Uint8List get pbBytes => writeToBuffer(); + + @TagNumber(1) + PublicKeyHash get validator => $_getN(1); + @TagNumber(1) + set validator(PublicKeyHash v) { + setField(0, v); + } + + @TagNumber(1) + bool hasValidator() => $_has(0); + @TagNumber(1) + void clearValidator() => clearField(1); + @TagNumber(1) + PublicKeyHash ensureValidator() => $_ensure(0); + + @TagNumber(2) + PublicKeyHash get withdrawer => $_getN(2); + @TagNumber(2) + set withdrawer(PublicKeyHash v) { + setField(2, v); + } + + @TagNumber(2) + bool hasWithdrawer() => $_has(1); + @TagNumber(2) + void clearWithdrawer() => clearField(2); + @TagNumber(2) + PublicKeyHash ensureWithdrawer() => $_ensure(1); +} diff --git a/lib/src/schema/stake_output.dart b/lib/src/schema/stake_output.dart index f1ecd31..763478f 100644 --- a/lib/src/schema/stake_output.dart +++ b/lib/src/schema/stake_output.dart @@ -4,7 +4,8 @@ class StakeOutput extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('StakeOutput', package: const PackageName('witnet'), createEmptyInstance: create) ..a(1, 'value', PbFieldType.OU6, defaultOrMaker: Int64.ZERO) - ..aOM(2, 'authorization', subBuilder: KeyedSignature.create) + ..aOM(2, 'key', subBuilder: PublicKeyHash.create) + ..aOM(3, 'authorization', subBuilder: KeyedSignature.create) ..hasRequiredFields = false; static StakeOutput create() => StakeOutput._(); @@ -22,12 +23,18 @@ class StakeOutput extends GeneratedMessage { factory StakeOutput({ int? value, + PublicKeyHash? key, KeyedSignature? authorization, }) { final _result = create(); if (value != null) { _result.value = Int64(value); } + + if (key != null) { + _result.key = key; + } + if (authorization != null) { _result.authorization = authorization; } @@ -40,11 +47,14 @@ class StakeOutput extends GeneratedMessage { @override factory StakeOutput.fromJson(Map json) => StakeOutput( value: json["value"], + + key: PublicKeyHash.fromAddress(json["key"]), authorization: KeyedSignature.fromJson(json["authorization"]), ); Map jsonMap({bool asHex = false}) => { "value": value.toInt(), + "key": key.address, "authorization": authorization.jsonMap(asHex: asHex), }; @@ -66,16 +76,32 @@ class StakeOutput extends GeneratedMessage { void clearValue() => clearField(1); @TagNumber(2) - KeyedSignature get authorization => $_getN(2); + PublicKeyHash get key => $_getN(2); @TagNumber(2) - set authorization(KeyedSignature v) { + set key(PublicKeyHash v) { + setField(2, v); } @TagNumber(2) - bool hasAuthorization() => $_has(1); + bool hasKey() => $_has(1); @TagNumber(2) - void clearAuthorization() => clearField(2); + void clearKey() => clearField(2); @TagNumber(2) - PublicKeyHash ensureAuthorization() => $_ensure(1); + PublicKeyHash ensureKey() => $_ensure(1); + + @TagNumber(3) + KeyedSignature get authorization => $_getN(3); + @TagNumber(3) + set authorization(KeyedSignature v) { + setField(3, v); + } + + @TagNumber(3) + bool hasAuthorization() => $_has(2); + @TagNumber(3) + void clearAuthorization() => clearField(3); + @TagNumber(3) + PublicKeyHash ensureAuthorization() => $_ensure(2); + } diff --git a/lib/src/schema/unstake_body.dart b/lib/src/schema/unstake_body.dart index 00bcf62..f3805ef 100644 --- a/lib/src/schema/unstake_body.dart +++ b/lib/src/schema/unstake_body.dart @@ -6,8 +6,6 @@ class UnstakeBody extends GeneratedMessage { ..aOM(1, 'operator', subBuilder: PublicKeyHash.create) ..aOM(2, 'withdrawal', subBuilder: ValueTransferOutput.create) - ..aOM(2, 'change', - subBuilder: ValueTransferOutput.create) ..hasRequiredFields = false; static UnstakeBody create() => UnstakeBody._(); @@ -27,7 +25,7 @@ class UnstakeBody extends GeneratedMessage { factory UnstakeBody({ PublicKeyHash? operator, ValueTransferOutput? withdrawal, - ValueTransferOutput? change, + }) { final _result = create(); if (operator != null) { @@ -36,9 +34,7 @@ class UnstakeBody extends GeneratedMessage { if (withdrawal != null) { _result.withdrawal = withdrawal; } - if (change != null) { - _result.change = change; - } + return _result; } @@ -54,7 +50,6 @@ class UnstakeBody extends GeneratedMessage { factory UnstakeBody.fromJson(Map json) => UnstakeBody( operator: PublicKeyHash.fromAddress(json["operator"]), withdrawal: ValueTransferOutput.fromJson(json["withdrawal"]), - change: ValueTransferOutput.fromJson(json["change"]), ); factory UnstakeBody.fromPbBytes(Uint8List buffer) => @@ -65,7 +60,6 @@ class UnstakeBody extends GeneratedMessage { Map jsonMap({bool asHex = false}) => { "operator": operator.address, "withdrawal": withdrawal.jsonMap(asHex: asHex), - "change": change.jsonMap(asHex: asHex), }; Uint8List get pbBytes => writeToBuffer(); @@ -106,17 +100,4 @@ class UnstakeBody extends GeneratedMessage { @TagNumber(2) ValueTransferOutput ensureWithdrawal() => $_ensure(1); - @TagNumber(3) - ValueTransferOutput get change => $_getN(2); - @TagNumber(3) - set change(ValueTransferOutput v) { - setField(3, v); - } - - @TagNumber(3) - bool hasChange() => $_has(2); - @TagNumber(3) - void clearChange() => clearField(3); - @TagNumber(3) - ValueTransferOutput ensureChange() => $_ensure(2); } diff --git a/lib/src/schema/unstake_transaction.dart b/lib/src/schema/unstake_transaction.dart index eec33db..db23ea6 100644 --- a/lib/src/schema/unstake_transaction.dart +++ b/lib/src/schema/unstake_transaction.dart @@ -1,10 +1,12 @@ part of 'schema.dart'; + class UnstakeTransaction extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('UnstakeTransaction', package: const PackageName('witnet'), createEmptyInstance: create) ..aOM(1, 'body', subBuilder: UnstakeBody.create) - ..pc(2, 'signatures', PbFieldType.PM, + + ..pc(2, 'signature', PbFieldType.PM, subBuilder: KeyedSignature.create) ..hasRequiredFields = false; @@ -25,14 +27,15 @@ class UnstakeTransaction extends GeneratedMessage { factory UnstakeTransaction({ UnstakeBody? body, - Iterable? signatures, + + KeyedSignature? signature, }) { final _result = create(); if (body != null) { _result.body = body; } - if (signatures != null) { - _result.signatures.addAll(signatures); + if (signature != null) { + _result.signature = signature; } return _result; } @@ -44,8 +47,8 @@ class UnstakeTransaction extends GeneratedMessage { factory UnstakeTransaction.fromJson(Map json) => UnstakeTransaction( body: UnstakeBody.fromJson(json["body"]), - signatures: List.from( - json["signatures"].map((x) => KeyedSignature.fromJson(x))), + signature: KeyedSignature.fromJson( json["signature"]), + ); @override @@ -57,8 +60,8 @@ class UnstakeTransaction extends GeneratedMessage { Map jsonMap({bool asHex = false}) => { "body": body.jsonMap(asHex: asHex), - "signatures": - List.from(signatures.map((x) => x.jsonMap(asHex: asHex))), + "signature": signature.jsonMap(asHex: asHex) + }; String get transactionID => bytesToHex(body.hash); @@ -85,5 +88,17 @@ class UnstakeTransaction extends GeneratedMessage { UnstakeBody ensureBody() => $_ensure(0); @TagNumber(2) - List get signatures => $_getList(1); + KeyedSignature get signature => $_getN(1); + + @TagNumber(2) + bool hasSignature() => $_has(1); + @TagNumber(2) + void clearSignature() => clearField(2); + @TagNumber(2) + UnstakeBody ensureSignature() => $_ensure(1); + @TagNumber(2) + set signature(KeyedSignature v) { + setField(2, v); + } + } From b276a61e54152d25e0741d2cf389afcfef78851b Mon Sep 17 00:00:00 2001 From: parodyBit <58690522+parodyBit@users.noreply.github.com> Date: Mon, 27 May 2024 06:47:49 -0600 Subject: [PATCH 3/4] fix: stake / unstake schema --- example/stake_transaction_example.dart | 15 +++++++- lib/src/schema/public_key.dart | 4 ++ lib/src/schema/stake_body.dart | 2 +- lib/src/schema/stake_key.dart | 3 +- lib/src/schema/stake_output.dart | 19 ++++------ lib/src/schema/transaction.dart | 49 ++++++++++++++++++++++++- lib/src/schema/unstake_transaction.dart | 3 +- 7 files changed, 77 insertions(+), 18 deletions(-) diff --git a/example/stake_transaction_example.dart b/example/stake_transaction_example.dart index fde8700..1d04ddd 100644 --- a/example/stake_transaction_example.dart +++ b/example/stake_transaction_example.dart @@ -29,6 +29,12 @@ void main() async { /// The authorization by the node KeyedSignature authorization = signHash(pkh, masterNode.privateKey); + /// Build the Stake Key + StakeKey stakeKey = StakeKey( + validator: authorization.publicKey.pkh, + withdrawer: PublicKeyHash.fromAddress(withdrawer.address.address), + ); + /// build stake transaction body StakeBody body = StakeBody( inputs: [ @@ -36,6 +42,7 @@ void main() async { ], output: StakeOutput( value: MINIMUM_STAKEABLE_AMOUNT_WITS, + key: stakeKey, authorization: authorization, ), ); @@ -52,8 +59,12 @@ void main() async { /// var response = await nodeClient.inventory(stake.jsonMap()); /// UnstakeBody unstakeBody = UnstakeBody( - operator: PublicKeyHash.fromAddress(""), - withdrawal: ValueTransferOutput.fromJson({})); + operator: PublicKeyHash.fromAddress(withdrawer.address.address), + withdrawal: ValueTransferOutput.fromJson({ + "pkh": withdrawer.address.address, + "time_lock": 0, + "value": 1, + })); KeyedSignature unstakeSignature = signHash(bytesToHex(unstakeBody.hash), masterNode.privateKey); diff --git a/lib/src/schema/public_key.dart b/lib/src/schema/public_key.dart index f157650..0bd44b7 100644 --- a/lib/src/schema/public_key.dart +++ b/lib/src/schema/public_key.dart @@ -64,6 +64,10 @@ class PublicKey extends GeneratedMessage { Uint8List get pbBytes => writeToBuffer(); + PublicKeyHash get pkh => PublicKeyHash( + hash: sha256(data: Uint8List.fromList(publicKey)).sublist(0, 20), + ); + @TagNumber(1) List get publicKey => $_getN(0); @TagNumber(1) diff --git a/lib/src/schema/stake_body.dart b/lib/src/schema/stake_body.dart index 3f7ed41..eac5f7f 100644 --- a/lib/src/schema/stake_body.dart +++ b/lib/src/schema/stake_body.dart @@ -5,7 +5,7 @@ class StakeBody extends GeneratedMessage { package: const PackageName('witnet'), createEmptyInstance: create) ..pc(1, 'inputs', PbFieldType.PM, subBuilder: Input.create) ..aOM(2, 'output', subBuilder: StakeOutput.create) - ..aOM(2, 'change', + ..aOM(3, 'change', subBuilder: ValueTransferOutput.create) ..hasRequiredFields = false; diff --git a/lib/src/schema/stake_key.dart b/lib/src/schema/stake_key.dart index 850877c..89a318c 100644 --- a/lib/src/schema/stake_key.dart +++ b/lib/src/schema/stake_key.dart @@ -1,6 +1,7 @@ part of 'schema.dart'; + class StakeKey extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('StakeOutput', package: const PackageName('witnet'), createEmptyInstance: create) @@ -58,7 +59,7 @@ class StakeKey extends GeneratedMessage { PublicKeyHash get validator => $_getN(1); @TagNumber(1) set validator(PublicKeyHash v) { - setField(0, v); + setField(1, v); } @TagNumber(1) diff --git a/lib/src/schema/stake_output.dart b/lib/src/schema/stake_output.dart index 763478f..0da3bbe 100644 --- a/lib/src/schema/stake_output.dart +++ b/lib/src/schema/stake_output.dart @@ -4,7 +4,7 @@ class StakeOutput extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('StakeOutput', package: const PackageName('witnet'), createEmptyInstance: create) ..a(1, 'value', PbFieldType.OU6, defaultOrMaker: Int64.ZERO) - ..aOM(2, 'key', subBuilder: PublicKeyHash.create) + ..aOM(2, 'key', subBuilder: StakeKey.create) ..aOM(3, 'authorization', subBuilder: KeyedSignature.create) ..hasRequiredFields = false; @@ -23,7 +23,7 @@ class StakeOutput extends GeneratedMessage { factory StakeOutput({ int? value, - PublicKeyHash? key, + StakeKey? key, KeyedSignature? authorization, }) { final _result = create(); @@ -47,14 +47,13 @@ class StakeOutput extends GeneratedMessage { @override factory StakeOutput.fromJson(Map json) => StakeOutput( value: json["value"], - - key: PublicKeyHash.fromAddress(json["key"]), + key: StakeKey.fromJson(json["key"]), authorization: KeyedSignature.fromJson(json["authorization"]), ); Map jsonMap({bool asHex = false}) => { "value": value.toInt(), - "key": key.address, + "key": key.jsonMap(asHex: asHex), "authorization": authorization.jsonMap(asHex: asHex), }; @@ -76,10 +75,9 @@ class StakeOutput extends GeneratedMessage { void clearValue() => clearField(1); @TagNumber(2) - PublicKeyHash get key => $_getN(2); + StakeKey get key => $_getN(2); @TagNumber(2) - set key(PublicKeyHash v) { - + set key(StakeKey v) { setField(2, v); } @@ -88,7 +86,7 @@ class StakeOutput extends GeneratedMessage { @TagNumber(2) void clearKey() => clearField(2); @TagNumber(2) - PublicKeyHash ensureKey() => $_ensure(1); + StakeKey ensureKey() => $_ensure(1); @TagNumber(3) KeyedSignature get authorization => $_getN(3); @@ -102,6 +100,5 @@ class StakeOutput extends GeneratedMessage { @TagNumber(3) void clearAuthorization() => clearField(3); @TagNumber(3) - PublicKeyHash ensureAuthorization() => $_ensure(2); - + KeyedSignature ensureAuthorization() => $_ensure(2); } diff --git a/lib/src/schema/transaction.dart b/lib/src/schema/transaction.dart index 4a64ac9..ecc9c6a 100644 --- a/lib/src/schema/transaction.dart +++ b/lib/src/schema/transaction.dart @@ -7,6 +7,8 @@ enum TransactionKind { reveal, tally, mint, + stake, + unstake, notSet } @@ -17,6 +19,8 @@ const Map _Transaction_KindByTag = { 4: TransactionKind.reveal, 5: TransactionKind.tally, 6: TransactionKind.mint, + 7: TransactionKind.stake, + 8: TransactionKind.unstake, 0: TransactionKind.notSet }; @@ -36,6 +40,10 @@ class Transaction extends GeneratedMessage { protoName: 'Tally', subBuilder: TallyTransaction.create) ..aOM(6, 'Mint', protoName: 'Mint', subBuilder: MintTransaction.create) + ..aOM(6, 'Mint', + protoName: 'Stake', subBuilder: StakeTransaction.create) + ..aOM(6, 'Mint', + protoName: 'Unstake', subBuilder: UnstakeTransaction.create) ..hasRequiredFields = false; static Transaction create() => Transaction._(); @@ -59,6 +67,8 @@ class Transaction extends GeneratedMessage { RevealTransaction? reveal, TallyTransaction? tally, MintTransaction? mint, + StakeTransaction? stake, + UnstakeTransaction? unstake, }) { final _result = create(); if (valueTransfer != null) { @@ -79,6 +89,12 @@ class Transaction extends GeneratedMessage { if (mint != null) { _result.mint = mint; } + if (stake != null) { + _result.stake = stake; + } + if (unstake != null) { + _result.unstake = unstake; + } return _result; } @@ -110,9 +126,12 @@ class Transaction extends GeneratedMessage { case 'Reveal': return Transaction( reveal: RevealTransaction.fromJson(_txn['Reveal'])); - case 'Tally': return Transaction(tally: TallyTransaction.fromJson(_txn['Tally'])); + case 'Stake': + return Transaction(stake: StakeTransaction.fromJson(_txn['Stake'])); + case 'Unstake': + return Transaction(unstake: UnstakeTransaction.fromJson(_txn['Unstake'])); } } else { throw ArgumentError('Invalid json'); @@ -250,4 +269,32 @@ class Transaction extends GeneratedMessage { void clearMint() => clearField(6); @TagNumber(6) MintTransaction ensureMint() => $_ensure(5); + + @TagNumber(7) + StakeTransaction get stake => $_getN(6); + @TagNumber(7) + set stake(StakeTransaction v) { + setField(7, v); + } + + @TagNumber(7) + bool hasStake() => $_has(6); + @TagNumber(7) + void clearStake() => clearField(7); + @TagNumber(7) + StakeTransaction ensureStake() => $_ensure(6); + + + @TagNumber(8) + UnstakeTransaction get unstake => $_getN(7); + @TagNumber(8) + set unstake(UnstakeTransaction v) { + setField(8, v); + } + @TagNumber(8) + bool hasUnstake() => $_has(7); + @TagNumber(8) + void clearUnstake() => clearField(8); + @TagNumber(8) + UnstakeTransaction ensureUnstake() => $_ensure(7); } diff --git a/lib/src/schema/unstake_transaction.dart b/lib/src/schema/unstake_transaction.dart index db23ea6..b01d7ed 100644 --- a/lib/src/schema/unstake_transaction.dart +++ b/lib/src/schema/unstake_transaction.dart @@ -6,8 +6,7 @@ class UnstakeTransaction extends GeneratedMessage { package: const PackageName('witnet'), createEmptyInstance: create) ..aOM(1, 'body', subBuilder: UnstakeBody.create) - ..pc(2, 'signature', PbFieldType.PM, - subBuilder: KeyedSignature.create) + ..aOM(2, 'signature', subBuilder: KeyedSignature.create) ..hasRequiredFields = false; static UnstakeTransaction create() => UnstakeTransaction._(); From 4ad5afa5160e98953d81076066a6b3c9f682591e Mon Sep 17 00:00:00 2001 From: gabaldon Date: Tue, 4 Jun 2024 15:52:07 +0200 Subject: [PATCH 4/4] fix: wip --- .../hd_wallet/extended_private_key.dart | 1 + lib/src/data_structures/utxo_pool.dart | 8 ++- lib/src/schema/stake_key.dart | 20 +++--- lib/src/schema/stake_output.dart | 27 ++++--- lib/src/schema/transaction.dart | 70 +++++++++++++++---- lib/src/schema/unstake_body.dart | 2 - lib/src/schema/unstake_transaction.dart | 8 +-- 7 files changed, 92 insertions(+), 44 deletions(-) diff --git a/lib/src/crypto/hd_wallet/extended_private_key.dart b/lib/src/crypto/hd_wallet/extended_private_key.dart index c875eb4..f1e16f0 100644 --- a/lib/src/crypto/hd_wallet/extended_private_key.dart +++ b/lib/src/crypto/hd_wallet/extended_private_key.dart @@ -146,6 +146,7 @@ class Xprv extends ExtendedKey { } factory Xprv.fromEncryptedXprv(String xprv, String password) { + // throw 'Error from encrypted xprv'; try { Bech32 bech = bech32.decode(xprv); List checksum = createChecksum(bech.hrp, bech.data); diff --git a/lib/src/data_structures/utxo_pool.dart b/lib/src/data_structures/utxo_pool.dart index caed66c..c5dc955 100644 --- a/lib/src/data_structures/utxo_pool.dart +++ b/lib/src/data_structures/utxo_pool.dart @@ -41,6 +41,8 @@ class UtxoPool { } List sortUtxos(UtxoSelectionStrategy utxoSelectionStrategy) { + print(utxoSelectionStrategy); + print('...sortUtxos.. 0. ${map.values.toList().length}'); List sortedUtxos; switch (utxoSelectionStrategy) { case UtxoSelectionStrategy.Random: @@ -68,6 +70,7 @@ class UtxoPool { }); } } + print('...sortUtxos.. 1. ${sortedUtxos.length}'); return sortedUtxos; } @@ -75,6 +78,8 @@ class UtxoPool { required int amountNanoWit, required UtxoSelectionStrategy utxoStrategy, }) { + print('-------cover UTXOS-------'); + print('amount nanowit: $amountNanoWit'); List utxos = sortUtxos(utxoStrategy); if (utxos.isEmpty) { throw 'No UTXOS to select'; @@ -86,7 +91,8 @@ class UtxoPool { }); List selectedUtxos = []; - + print('utxos value: $utxoValue'); + print('Insufficient funds?? ${amountNanoWit > utxoValue}'); if (amountNanoWit > utxoValue) { throw 'Insufficient funds'; } diff --git a/lib/src/schema/stake_key.dart b/lib/src/schema/stake_key.dart index 89a318c..b8406e8 100644 --- a/lib/src/schema/stake_key.dart +++ b/lib/src/schema/stake_key.dart @@ -1,7 +1,5 @@ part of 'schema.dart'; - - class StakeKey extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('StakeOutput', package: const PackageName('witnet'), createEmptyInstance: create) @@ -41,14 +39,14 @@ class StakeKey extends GeneratedMessage { @override factory StakeKey.fromJson(Map json) => StakeKey( - validator: PublicKeyHash.fromAddress(json["validator"]), - withdrawer: PublicKeyHash.fromAddress(json["withdrawer"]), - ); + validator: PublicKeyHash.fromAddress(json["validator"]), + withdrawer: PublicKeyHash.fromAddress(json["withdrawer"]), + ); Map jsonMap({bool asHex = false}) => { - "validator": validator.address, - "withdrawer": withdrawer.address, - }; + "validator": validator.address, + "withdrawer": withdrawer.address, + }; @override BuilderInfo get info_ => _i; @@ -56,7 +54,7 @@ class StakeKey extends GeneratedMessage { Uint8List get pbBytes => writeToBuffer(); @TagNumber(1) - PublicKeyHash get validator => $_getN(1); + PublicKeyHash get validator => $_getN(0); @TagNumber(1) set validator(PublicKeyHash v) { setField(1, v); @@ -70,10 +68,10 @@ class StakeKey extends GeneratedMessage { PublicKeyHash ensureValidator() => $_ensure(0); @TagNumber(2) - PublicKeyHash get withdrawer => $_getN(2); + PublicKeyHash get withdrawer => $_getN(1); @TagNumber(2) set withdrawer(PublicKeyHash v) { - setField(2, v); + setField(1, v); } @TagNumber(2) diff --git a/lib/src/schema/stake_output.dart b/lib/src/schema/stake_output.dart index 0da3bbe..1036524 100644 --- a/lib/src/schema/stake_output.dart +++ b/lib/src/schema/stake_output.dart @@ -27,6 +27,9 @@ class StakeOutput extends GeneratedMessage { KeyedSignature? authorization, }) { final _result = create(); + print('result >>>>***** $value'); + print('result >>>>***** $key'); + print('result >>>>***** $authorization'); if (value != null) { _result.value = Int64(value); } @@ -38,6 +41,7 @@ class StakeOutput extends GeneratedMessage { if (authorization != null) { _result.authorization = authorization; } + print('result >>>>***** $_result'); return _result; } @@ -48,13 +52,16 @@ class StakeOutput extends GeneratedMessage { factory StakeOutput.fromJson(Map json) => StakeOutput( value: json["value"], key: StakeKey.fromJson(json["key"]), - authorization: KeyedSignature.fromJson(json["authorization"]), + authorization: json["authorization"] != null + ? KeyedSignature.fromJson(json["authorization"]) + : null, ); Map jsonMap({bool asHex = false}) => { "value": value.toInt(), "key": key.jsonMap(asHex: asHex), - "authorization": authorization.jsonMap(asHex: asHex), + "authorization": + authorization != null ? authorization!.jsonMap(asHex: asHex) : null, }; @override @@ -63,10 +70,10 @@ class StakeOutput extends GeneratedMessage { Uint8List get pbBytes => writeToBuffer(); @TagNumber(1) - Int64 get value => $_getI64(1); + Int64 get value => $_getI64(0); @TagNumber(1) set value(Int64 v) { - $_setInt64(0, v); + setField(1, v); } @TagNumber(1) @@ -75,7 +82,7 @@ class StakeOutput extends GeneratedMessage { void clearValue() => clearField(1); @TagNumber(2) - StakeKey get key => $_getN(2); + StakeKey get key => $_getN(1); @TagNumber(2) set key(StakeKey v) { setField(2, v); @@ -89,10 +96,12 @@ class StakeOutput extends GeneratedMessage { StakeKey ensureKey() => $_ensure(1); @TagNumber(3) - KeyedSignature get authorization => $_getN(3); + KeyedSignature? get authorization => $_getN(2); @TagNumber(3) - set authorization(KeyedSignature v) { - setField(3, v); + set authorization(KeyedSignature? v) { + if (v != null) { + setField(3, v); + } } @TagNumber(3) @@ -100,5 +109,5 @@ class StakeOutput extends GeneratedMessage { @TagNumber(3) void clearAuthorization() => clearField(3); @TagNumber(3) - KeyedSignature ensureAuthorization() => $_ensure(2); + KeyedSignature? ensureAuthorization() => $_ensure(2); } diff --git a/lib/src/schema/transaction.dart b/lib/src/schema/transaction.dart index ecc9c6a..4248b37 100644 --- a/lib/src/schema/transaction.dart +++ b/lib/src/schema/transaction.dart @@ -27,7 +27,7 @@ const Map _Transaction_KindByTag = { class Transaction extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('Transaction', package: const PackageName('witnet'), createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6]) + ..oo(0, [1, 2, 3, 4, 5, 6, 7, 8]) ..aOM(1, 'ValueTransfer', protoName: 'ValueTransfer', subBuilder: VTTransaction.create) ..aOM(2, 'DataRequest', @@ -40,9 +40,9 @@ class Transaction extends GeneratedMessage { protoName: 'Tally', subBuilder: TallyTransaction.create) ..aOM(6, 'Mint', protoName: 'Mint', subBuilder: MintTransaction.create) - ..aOM(6, 'Mint', + ..aOM(7, 'Stake', protoName: 'Stake', subBuilder: StakeTransaction.create) - ..aOM(6, 'Mint', + ..aOM(8, 'Unstake', protoName: 'Unstake', subBuilder: UnstakeTransaction.create) ..hasRequiredFields = false; @@ -131,7 +131,8 @@ class Transaction extends GeneratedMessage { case 'Stake': return Transaction(stake: StakeTransaction.fromJson(_txn['Stake'])); case 'Unstake': - return Transaction(unstake: UnstakeTransaction.fromJson(_txn['Unstake'])); + return Transaction( + unstake: UnstakeTransaction.fromJson(_txn['Unstake'])); } } else { throw ArgumentError('Invalid json'); @@ -142,16 +143,55 @@ class Transaction extends GeneratedMessage { String toRawJson({bool asHex = false}) => json.encode(jsonMap(asHex: asHex)); Map jsonMap({bool asHex = false}) { - final txType = hasDataRequest() ? 'DataRequest' : 'ValueTransfer'; - return { - "transaction": { - txType: { - "body": transaction.body.jsonMap(asHex: asHex), - "signatures": List.from( - transaction.signatures.map((x) => x.jsonMap(asHex: asHex))), + if (hasValueTransfer()) + return { + "transaction": { + 'ValueTransfer': { + "body": transaction.body.jsonMap(asHex: asHex), + "signatures": List.from( + transaction.signatures.map((x) => x.jsonMap(asHex: asHex))), + } } - } - }; + }; + if (hasDataRequest()) + return { + "transaction": { + 'DataRequest': { + "body": transaction.body.jsonMap(asHex: asHex), + "signatures": List.from( + transaction.signatures.map((x) => x.jsonMap(asHex: asHex))), + } + } + }; + if (hasStake()) + return { + "transaction": { + 'Stake': { + "body": transaction.body.jsonMap(asHex: asHex), + "signatures": List.from( + transaction.signatures.map((x) => x.jsonMap(asHex: asHex))), + }, + } + }; + if (hasUnstake()) + return { + "transaction": { + 'Unstake': { + "body": transaction.body.jsonMap(asHex: asHex), + "signature": transaction.signature.jsonMap(asHex: asHex), + } + } + }; + else + return { + "transaction": { + 'ValueTransfer': { + "body": transaction.body.jsonMap(asHex: asHex), + "signatures": List.from( + transaction.signatures.map((x) => x.jsonMap(asHex: asHex))), + } + } + }; } @override @@ -180,6 +220,8 @@ class Transaction extends GeneratedMessage { if (hasReveal()) return reveal; if (hasTally()) return tally; if (hasMint()) return mint; + if (hasStake()) return stake; + if (hasUnstake()) return unstake; } TransactionKind whichKind() => _Transaction_KindByTag[$_whichOneof(0)]!; @@ -284,13 +326,13 @@ class Transaction extends GeneratedMessage { @TagNumber(7) StakeTransaction ensureStake() => $_ensure(6); - @TagNumber(8) UnstakeTransaction get unstake => $_getN(7); @TagNumber(8) set unstake(UnstakeTransaction v) { setField(8, v); } + @TagNumber(8) bool hasUnstake() => $_has(7); @TagNumber(8) diff --git a/lib/src/schema/unstake_body.dart b/lib/src/schema/unstake_body.dart index f3805ef..3ea59c0 100644 --- a/lib/src/schema/unstake_body.dart +++ b/lib/src/schema/unstake_body.dart @@ -25,7 +25,6 @@ class UnstakeBody extends GeneratedMessage { factory UnstakeBody({ PublicKeyHash? operator, ValueTransferOutput? withdrawal, - }) { final _result = create(); if (operator != null) { @@ -99,5 +98,4 @@ class UnstakeBody extends GeneratedMessage { void clearWithdrawal() => clearField(2); @TagNumber(2) ValueTransferOutput ensureWithdrawal() => $_ensure(1); - } diff --git a/lib/src/schema/unstake_transaction.dart b/lib/src/schema/unstake_transaction.dart index b01d7ed..1848dbc 100644 --- a/lib/src/schema/unstake_transaction.dart +++ b/lib/src/schema/unstake_transaction.dart @@ -1,11 +1,9 @@ part of 'schema.dart'; - class UnstakeTransaction extends GeneratedMessage { static final BuilderInfo _i = BuilderInfo('UnstakeTransaction', package: const PackageName('witnet'), createEmptyInstance: create) ..aOM(1, 'body', subBuilder: UnstakeBody.create) - ..aOM(2, 'signature', subBuilder: KeyedSignature.create) ..hasRequiredFields = false; @@ -26,7 +24,6 @@ class UnstakeTransaction extends GeneratedMessage { factory UnstakeTransaction({ UnstakeBody? body, - KeyedSignature? signature, }) { final _result = create(); @@ -46,8 +43,7 @@ class UnstakeTransaction extends GeneratedMessage { factory UnstakeTransaction.fromJson(Map json) => UnstakeTransaction( body: UnstakeBody.fromJson(json["body"]), - signature: KeyedSignature.fromJson( json["signature"]), - + signature: KeyedSignature.fromJson(json["signature"]), ); @override @@ -60,7 +56,6 @@ class UnstakeTransaction extends GeneratedMessage { Map jsonMap({bool asHex = false}) => { "body": body.jsonMap(asHex: asHex), "signature": signature.jsonMap(asHex: asHex) - }; String get transactionID => bytesToHex(body.hash); @@ -99,5 +94,4 @@ class UnstakeTransaction extends GeneratedMessage { set signature(KeyedSignature v) { setField(2, v); } - }