From bfaf8315a2b9f11d2390a463191af0174de62df9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 7 Mar 2019 13:14:13 +0300 Subject: [PATCH 01/28] Updated on 2026-08-14 --- .idea/misc.xml | 35 +++++++++++++++++++ .../java/com/tangem/data/network/Server.java | 3 ++ .../data/network/ServerApiRootstock.java | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 703e5d4b89..cd2f3a654d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,6 +5,41 @@ + + + + diff --git a/app/src/main/java/com/tangem/data/network/Server.java b/app/src/main/java/com/tangem/data/network/Server.java index 9be4f58449..832e0495c2 100644 --- a/app/src/main/java/com/tangem/data/network/Server.java +++ b/app/src/main/java/com/tangem/data/network/Server.java @@ -32,6 +32,9 @@ public class Server { } } + /** + * https://public-node.rsk.co/ + */ public static class ApiRootstock { public static final String URL_ROOTSTOCK = ServerURL.API_ROOTSTOCK; diff --git a/app/src/main/java/com/tangem/data/network/ServerApiRootstock.java b/app/src/main/java/com/tangem/data/network/ServerApiRootstock.java index 0bcf5b7b4f..198f5cc6b0 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiRootstock.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiRootstock.java @@ -16,7 +16,7 @@ public class ServerApiRootstock { /** * HTTP - * Infura + * Rootstock *

* eth_getBalance * eth_getTransactionCount From 241b29c5df840c5320e6014eb5d979e82d76cc3f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 18 Mar 2019 17:58:56 +0300 Subject: [PATCH 02/28] Updated on 2026-08-14 --- .idea/gradle.xml | 1 + app/build.gradle | 1 + .../main/java/com/tangem/data/Blockchain.java | 14 +- .../com/tangem/data/network/RippleApi.java | 15 + .../tangem/data/network/ServerApiRipple.java | 114 +++ .../tangem/data/network/model/RippleBody.java | 24 + .../data/network/model/RippleResponse.kt | 52 ++ .../tangem/domain/wallet/xrp/XrpBase58.java | 115 +++ .../com/tangem/domain/wallet/xrp/XrpData.java | 78 ++ .../tangem/domain/wallet/xrp/XrpEngine.java | 411 +++++++++ ripple-core/.gitignore | 1 + ripple-core/README.md | 391 +++++++++ ripple-core/build.gradle | 52 ++ ripple-core/src/main/java/README.java | 206 +++++ .../com/ripple/core/binary/FileSTWriter.java | 32 + .../java/com/ripple/core/binary/STReader.java | 126 +++ .../java/com/ripple/core/binary/STWriter.java | 71 ++ .../java/com/ripple/core/cache/SLECache.java | 110 +++ .../com/ripple/core/coretypes/AccountID.java | 188 +++++ .../com/ripple/core/coretypes/Amount.java | 790 ++++++++++++++++++ .../java/com/ripple/core/coretypes/Blob.java | 119 +++ .../com/ripple/core/coretypes/Currency.java | 250 ++++++ .../java/com/ripple/core/coretypes/Flags.java | 35 + .../java/com/ripple/core/coretypes/Issue.java | 101 +++ .../com/ripple/core/coretypes/IssuePair.java | 36 + .../com/ripple/core/coretypes/PathSet.java | 273 ++++++ .../com/ripple/core/coretypes/Quality.java | 26 + .../com/ripple/core/coretypes/RippleDate.java | 82 ++ .../com/ripple/core/coretypes/STArray.java | 129 +++ .../com/ripple/core/coretypes/STObject.java | 489 +++++++++++ .../core/coretypes/STObjectFormatter.java | 170 ++++ .../com/ripple/core/coretypes/Vector256.java | 141 ++++ .../core/coretypes/hash/HalfSha512.java | 68 ++ .../com/ripple/core/coretypes/hash/Hash.java | 155 ++++ .../ripple/core/coretypes/hash/Hash128.java | 70 ++ .../ripple/core/coretypes/hash/Hash160.java | 81 ++ .../ripple/core/coretypes/hash/Hash256.java | 146 ++++ .../com/ripple/core/coretypes/hash/Index.java | 159 ++++ .../coretypes/hash/prefixes/HashPrefix.java | 56 ++ .../coretypes/hash/prefixes/LedgerSpace.java | 38 + .../core/coretypes/hash/prefixes/Prefix.java | 5 + .../com/ripple/core/coretypes/uint/UInt.java | 209 +++++ .../ripple/core/coretypes/uint/UInt16.java | 106 +++ .../ripple/core/coretypes/uint/UInt32.java | 137 +++ .../ripple/core/coretypes/uint/UInt64.java | 112 +++ .../com/ripple/core/coretypes/uint/UInt8.java | 105 +++ .../com/ripple/core/enums/LedgerFlag.java | 29 + .../ripple/core/enums/TransactionFlag.java | 50 ++ .../ripple/core/fields/AccountIDField.java | 3 + .../com/ripple/core/fields/AmountField.java | 3 + .../com/ripple/core/fields/BlobField.java | 3 + .../java/com/ripple/core/fields/Field.java | 328 ++++++++ .../java/com/ripple/core/fields/HasField.java | 5 + .../com/ripple/core/fields/Hash128Field.java | 3 + .../com/ripple/core/fields/Hash160Field.java | 3 + .../com/ripple/core/fields/Hash256Field.java | 3 + .../com/ripple/core/fields/PathSetField.java | 3 + .../com/ripple/core/fields/STArrayField.java | 3 + .../com/ripple/core/fields/STObjectField.java | 3 + .../java/com/ripple/core/fields/Type.java | 35 + .../com/ripple/core/fields/UInt16Field.java | 3 + .../com/ripple/core/fields/UInt32Field.java | 3 + .../com/ripple/core/fields/UInt64Field.java | 3 + .../com/ripple/core/fields/UInt8Field.java | 3 + .../ripple/core/fields/Vector256Field.java | 3 + .../java/com/ripple/core/formats/Format.java | 66 ++ .../com/ripple/core/formats/LEFormat.java | 230 +++++ .../com/ripple/core/formats/TxFormat.java | 212 +++++ .../java/com/ripple/core/runtime/Value.java | 111 +++ .../ripple/core/serialized/BinaryParser.java | 99 +++ .../core/serialized/BinarySerializer.java | 94 +++ .../com/ripple/core/serialized/BytesList.java | 77 ++ .../com/ripple/core/serialized/BytesSink.java | 8 + .../com/ripple/core/serialized/MultiSink.java | 16 + .../core/serialized/SerializedType.java | 11 + .../core/serialized/StreamBinaryParser.java | 81 ++ .../ripple/core/serialized/StreamSink.java | 31 + .../core/serialized/TypeTranslator.java | 151 ++++ .../core/serialized/enums/EngineResult.java | 258 ++++++ .../serialized/enums/LedgerEntryType.java | 101 +++ .../serialized/enums/TransactionType.java | 103 +++ .../core/types/known/generic/Validation.java | 15 + .../core/types/known/sle/LedgerEntry.java | 59 ++ .../core/types/known/sle/LedgerHashes.java | 32 + .../types/known/sle/ThreadedLedgerEntry.java | 18 + .../types/known/sle/entries/AccountRoot.java | 71 ++ .../types/known/sle/entries/Amendments.java | 22 + .../core/types/known/sle/entries/Check.java | 40 + .../known/sle/entries/DepositPreauthLe.java | 18 + .../known/sle/entries/DirectoryNode.java | 88 ++ .../core/types/known/sle/entries/Escrow.java | 74 ++ .../types/known/sle/entries/FeeSettings.java | 22 + .../types/known/sle/entries/IHasOwners.java | 12 + .../known/sle/entries/IndexedLedgerEntry.java | 56 ++ .../core/types/known/sle/entries/Offer.java | 219 +++++ .../known/sle/entries/OfferDirectory.java | 20 + .../known/sle/entries/OwnerDirectory.java | 3 + .../types/known/sle/entries/PayChannel.java | 42 + .../types/known/sle/entries/RippleState.java | 224 +++++ .../types/known/sle/entries/SignerList.java | 32 + .../core/types/known/sle/entries/Ticket.java | 27 + .../core/types/known/tx/Transaction.java | 116 +++ .../types/known/tx/result/AffectedNode.java | 156 ++++ .../known/tx/result/TransactionMeta.java | 50 ++ .../known/tx/result/TransactionResult.java | 299 +++++++ .../known/tx/signed/SignedTransaction.java | 94 +++ .../core/types/known/tx/txns/AccountSet.java | 46 + .../core/types/known/tx/txns/CheckCancel.java | 14 + .../core/types/known/tx/txns/CheckCash.java | 23 + .../core/types/known/tx/txns/CheckCreate.java | 30 + .../types/known/tx/txns/DepositPreauth.java | 19 + .../types/known/tx/txns/EscrowCancel.java | 18 + .../types/known/tx/txns/EscrowCreate.java | 33 + .../types/known/tx/txns/EscrowFinish.java | 27 + .../core/types/known/tx/txns/OfferCancel.java | 13 + .../core/types/known/tx/txns/OfferCreate.java | 25 + .../core/types/known/tx/txns/Payment.java | 39 + .../known/tx/txns/PaymentChannelClaim.java | 31 + .../known/tx/txns/PaymentChannelCreate.java | 32 + .../known/tx/txns/PaymentChannelFund.java | 24 + .../types/known/tx/txns/SetRegularKey.java | 14 + .../types/known/tx/txns/SignerListSet.java | 20 + .../types/known/tx/txns/TicketCancel.java | 17 + .../types/known/tx/txns/TicketCreate.java | 22 + .../core/types/known/tx/txns/TrustSet.java | 25 + .../known/tx/txns/pseudo/EnableAmendment.java | 17 + .../types/known/tx/txns/pseudo/SetFee.java | 25 + .../core/types/ledger/LedgerHeader.java | 109 +++ .../core/types/shamap/AccountState.java | 341 ++++++++ .../types/shamap/AccountStateBuilder.java | 320 +++++++ .../ripple/core/types/shamap/BytesItem.java | 37 + .../core/types/shamap/HashedTreeWalker.java | 8 + .../ripple/core/types/shamap/LeafWalker.java | 5 + .../core/types/shamap/LedgerEntryItem.java | 45 + .../core/types/shamap/LedgerEntryVisitor.java | 7 + .../ripple/core/types/shamap/NodeStore.java | 64 ++ .../ripple/core/types/shamap/PathToIndex.java | 156 ++++ .../com/ripple/core/types/shamap/README.md | 319 +++++++ .../com/ripple/core/types/shamap/ShaMap.java | 30 + .../ripple/core/types/shamap/ShaMapDiff.java | 122 +++ .../ripple/core/types/shamap/ShaMapInner.java | 331 ++++++++ .../ripple/core/types/shamap/ShaMapItem.java | 11 + .../ripple/core/types/shamap/ShaMapLeaf.java | 34 + .../ripple/core/types/shamap/ShaMapNode.java | 47 ++ .../types/shamap/TransactionResultItem.java | 38 + .../shamap/TransactionResultVisitor.java | 6 + .../core/types/shamap/TransactionTree.java | 43 + .../ripple/core/types/shamap/TreeWalker.java | 6 + .../src/main/java/com/ripple/crypto/Seed.java | 85 ++ .../ripple/crypto/ecdsa/ECDSASignature.java | 155 ++++ .../java/com/ripple/crypto/ecdsa/K256.java | 103 +++ .../com/ripple/crypto/ecdsa/K256KeyPair.java | 54 ++ .../ripple/crypto/ecdsa/K256VerifyingKey.java | 55 ++ .../com/ripple/crypto/ecdsa/SECP256K1.java | 42 + .../com/ripple/crypto/ed25519/ED25519.java | 9 + .../com/ripple/crypto/ed25519/EDKeyPair.java | 52 ++ .../ripple/crypto/ed25519/EDVerifyingKey.java | 58 ++ .../java/com/ripple/crypto/keys/IKeyPair.java | 6 + .../com/ripple/crypto/keys/IVerifyingKey.java | 29 + .../ripple/encodings/addresses/Addresses.java | 77 ++ .../java/com/ripple/encodings/base58/B58.java | 9 + .../com/ripple/encodings/basex/BaseX.java | 231 +++++ .../basex/EncodingFormatException.java | 7 + .../com/ripple/encodings/basex/IBaseX.java | 41 + .../java/com/ripple/encodings/common/B16.java | 20 + .../java/com/ripple/encodings/common/B64.java | 12 + .../main/java/com/ripple/utils/HashUtils.java | 62 ++ .../main/java/com/ripple/utils/Sha512.java | 53 ++ .../src/main/java/com/ripple/utils/Utils.java | 58 ++ settings.gradle | 2 +- 170 files changed, 13844 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/tangem/data/network/RippleApi.java create mode 100644 app/src/main/java/com/tangem/data/network/ServerApiRipple.java create mode 100644 app/src/main/java/com/tangem/data/network/model/RippleBody.java create mode 100644 app/src/main/java/com/tangem/data/network/model/RippleResponse.kt create mode 100644 app/src/main/java/com/tangem/domain/wallet/xrp/XrpBase58.java create mode 100644 app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java create mode 100644 app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java create mode 100644 ripple-core/.gitignore create mode 100644 ripple-core/README.md create mode 100644 ripple-core/build.gradle create mode 100644 ripple-core/src/main/java/README.java create mode 100644 ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java create mode 100644 ripple-core/src/main/java/com/ripple/core/binary/STReader.java create mode 100644 ripple-core/src/main/java/com/ripple/core/binary/STWriter.java create mode 100644 ripple-core/src/main/java/com/ripple/core/cache/SLECache.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java create mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java create mode 100644 ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java create mode 100644 ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/AmountField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/BlobField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/HasField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Type.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java create mode 100644 ripple-core/src/main/java/com/ripple/core/formats/Format.java create mode 100644 ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java create mode 100644 ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java create mode 100644 ripple-core/src/main/java/com/ripple/core/runtime/Value.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java create mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/README.md create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java create mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/Seed.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java create mode 100644 ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/base58/B58.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/common/B16.java create mode 100644 ripple-core/src/main/java/com/ripple/encodings/common/B64.java create mode 100644 ripple-core/src/main/java/com/ripple/utils/HashUtils.java create mode 100644 ripple-core/src/main/java/com/ripple/utils/Sha512.java create mode 100644 ripple-core/src/main/java/com/ripple/utils/Utils.java diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 1dde4f60b5..dbe604a60c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -11,6 +11,7 @@ diff --git a/app/build.gradle b/app/build.gradle index ec8de2db1a..d6bf56e099 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,6 +44,7 @@ android { } dependencies { + implementation project(':ripple-core') implementation project(':card-common') implementation project(':card-android') implementation project(':server-android') diff --git a/app/src/main/java/com/tangem/data/Blockchain.java b/app/src/main/java/com/tangem/data/Blockchain.java index e229b98330..31e89d72ee 100644 --- a/app/src/main/java/com/tangem/data/Blockchain.java +++ b/app/src/main/java/com/tangem/data/Blockchain.java @@ -12,12 +12,13 @@ public enum Blockchain { Ethereum("ETH", "ETH", 1.0, R.drawable.ic_logo_ethereum, "Ethereum"), EthereumTestNet("ETH/test", "ETH", 1.0, R.drawable.ic_logo_ethereum_testnet, "Ethereum Testnet"), Token("Token", "ETH", 1.0, R.drawable.ic_logo_bat_token, "Ethereum"), - NftToken("NftToken", "", 1.0, R.drawable.ic_logo_bat_token, "Ethereum"), + NftToken("NftToken", "", 1.0, R.drawable.tangem2, "Ethereum"), BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.ic_logo_bitcoin_cash, "Bitcoin Cash"), - Litecoin("LTC", "LTC", 100000000.0, R.drawable.ic_logo_bitcoin, "Litecoin"), - Rootstock("RSK", "RBTC", 1.0, R.drawable.ic_logo_bitcoin, "Rootstock"), - RootstockToken("Token", "RBTC", 1.0, R.drawable.ic_logo_bat_token, "Rootstock"), - Cardano("CARDANO", "ADA", 1000000.0,R.drawable.ic_logo_bitcoin, "Cardano"); + Litecoin("LTC", "LTC", 100000000.0, R.drawable.tangem2, "Litecoin"), + Rootstock("RSK", "RBTC", 1.0, R.drawable.tangem2, "Rootstock"), + RootstockToken("Token", "RBTC", 1.0, R.drawable.tangem2, "Rootstock"), + Cardano("CARDANO", "ADA", 1000000.0, R.drawable.tangem2, "Cardano"), + Ripple ("XRP", "XRP", 1000000.0, R.drawable.tangem2, "Ripple"); Blockchain(String ID, String currency, double multiplier, int imageResource, String officialName) { mID = ID; @@ -92,6 +93,9 @@ public enum Blockchain { case "BTC": return R.drawable.ic_logo_bitcoin; + case "BCH": + return R.drawable.ic_logo_bitcoin_cash; + case "Token": if (symbolName.equals("SEED")) return R.drawable.ic_logo_seed; diff --git a/app/src/main/java/com/tangem/data/network/RippleApi.java b/app/src/main/java/com/tangem/data/network/RippleApi.java new file mode 100644 index 0000000000..1d457ad859 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/RippleApi.java @@ -0,0 +1,15 @@ +package com.tangem.data.network; + +import com.tangem.data.network.model.RippleBody; +import com.tangem.data.network.model.RippleResponse; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface RippleApi { + @Headers("Content-Type: application/json") + @POST + Call ripple(@Body RippleBody body); +} diff --git a/app/src/main/java/com/tangem/data/network/ServerApiRipple.java b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java new file mode 100644 index 0000000000..ba5c356b47 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java @@ -0,0 +1,114 @@ +package com.tangem.data.network; + +import android.util.Log; + +import com.tangem.App; +import com.tangem.data.network.model.RippleBody; +import com.tangem.data.network.model.RippleResponse; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.NonNull; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class ServerApiRipple { + private static String TAG = ServerApiRipple.class.getSimpleName(); + + public static final String RIPPLE_ACCOUNT_INFO = "account_info"; + public static final String RIPPLE_ACCOUNT_UNCONFIRMED = "account_unconfirmed"; + public static final String RIPPLE_SUBMIT = "submit"; + public static final String RIPPLE_FEE = "fee"; + + private int requestsCount=0; + + public static String lastNode; + + public boolean isRequestsSequenceCompleted() { + Log.i(TAG, String.format("isRequestsSequenceCompleted: %s (%d requests left)", String.valueOf(requestsCount <= 0), requestsCount)); + return requestsCount <= 0; + } + + private ResponseListener responseListener; + + public interface ResponseListener { + void onSuccess(String method, RippleResponse infuraResponse); + + void onFail(String method, String message); + } + + public void setResponseListener(ResponseListener listener) { + responseListener = listener; + } + + public void requestData(String method, int id, String wallet, String tx) { + requestsCount++; + String rippleURL = "http://s1.ripple.com:51234/"; //TODO: make random selection + lastNode = rippleURL; //TODO: show node instead of URL + + Retrofit retrofitRipple = new Retrofit.Builder() + .baseUrl(rippleURL) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + + RippleApi rippleApi = retrofitRipple.create(RippleApi.class); + + RippleBody rippleBody; + HashMap paramsMap; + + switch (method) { + case RIPPLE_ACCOUNT_INFO: + paramsMap = new HashMap<>(); + paramsMap.put("account", wallet); + paramsMap.put("ledger_index", "validated"); + rippleBody = new RippleBody(method, paramsMap); + break; + + case RIPPLE_ACCOUNT_UNCONFIRMED: + paramsMap = new HashMap<>(); + paramsMap.put("account", wallet); + paramsMap.put("ledger_index", "current"); +// paramsMap.put("queue", "true"); TODO: make queue check if needed + rippleBody = new RippleBody(RIPPLE_ACCOUNT_INFO, paramsMap); + break; + + case RIPPLE_FEE: + rippleBody = new RippleBody(method, new HashMap<>()); + break; + + case RIPPLE_SUBMIT: + paramsMap = new HashMap<>(); + paramsMap.put("tx_blob", tx); + rippleBody = new RippleBody(method, paramsMap); + break; + + default: + rippleBody = new RippleBody(); + } + + Call call = rippleApi.ripple(rippleBody); + call.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.code() == 200) { + requestsCount--; + responseListener.onSuccess(method, response.body()); + Log.i(TAG, "requestData " + method + " onResponse " + response.code()); + } else { + responseListener.onFail(method, String.valueOf(response.code())); + Log.e(TAG, "requestData " + method + " onResponse " + response.code()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + responseListener.onFail(method, String.valueOf(t.getMessage())); + Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage()); + } + }); + } +} diff --git a/app/src/main/java/com/tangem/data/network/model/RippleBody.java b/app/src/main/java/com/tangem/data/network/model/RippleBody.java new file mode 100644 index 0000000000..0423f357a1 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/model/RippleBody.java @@ -0,0 +1,24 @@ +package com.tangem.data.network.model; + +import java.util.ArrayList; +import java.util.HashMap; + +public class RippleBody { + private String method; + private ArrayList> params; + + public RippleBody() { + } + + //for RIPPLE_FEE + public RippleBody(String method) { + this.method = method; + } + + public RippleBody(String method, HashMap paramsMap) { + this.method = method; + ArrayList> paramsList = new ArrayList<>(); + paramsList.add(paramsMap); + this.params = paramsList; + } +} diff --git a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt new file mode 100644 index 0000000000..6c61b6abb0 --- /dev/null +++ b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt @@ -0,0 +1,52 @@ +package com.tangem.data.network.model + +import com.google.gson.annotations.SerializedName + +data class RippleResponse( + @SerializedName("result") + var result: RippleResult? = null +) + +data class RippleResult( + @SerializedName("account_data") + var account_data: RippleAccountData? = null, + + @SerializedName("validated") + var validated: Boolean? = null, + + //for RIPPLE_FEE + @SerializedName("drops") + var drops: FeeDrops? = null, + + //for RIPPLE_SUBMIT + @SerializedName("engine_result") + var engine_result: String? = null, + + //for RIPPLE_SUBMIT + @SerializedName ("engine_result_message") + var engine_result_message: String? = null +) + +data class RippleAccountData( + @SerializedName("Account") + var account: String? = null, + + @SerializedName("Balance") + var balance: String? = null, + + @SerializedName("Sequence") + var sequence: Int? = null +) + +data class FeeDrops( + //enough to put tx to queue + @SerializedName("minimum_fee") + var minimum_fee: String? = null, + + //enough to put tx to current ledger + @SerializedName("open_ledger_fee") + var open_ledger_fee: String? = null, + + @SerializedName("median_fee") + var median_fee: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpBase58.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpBase58.java new file mode 100644 index 0000000000..7a34b0d289 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpBase58.java @@ -0,0 +1,115 @@ +package com.tangem.domain.wallet.xrp; + +import java.math.BigInteger; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class XrpBase58 { + private static final char[] BASE58 = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz".toCharArray(); + + private static final int BASE58_CHUNK_DIGITS = 10;//how many base 58 digits fits in long + private static final BigInteger BASE58_CHUNK_MOD = BigInteger.valueOf(0x5fa8624c7fba400L); //58^BASE58_CHUNK_DIGITS + private static final byte[] BASE58_VALUES = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, + -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, + -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + + public static byte[] decodeBase58(String input) { + if (input == null) { + return null; + } + input = input.trim(); + if (input.length() == 0) { + return new byte[0]; + } + BigInteger resultNum = BigInteger.ZERO; + int nLeadingZeros = 0; + while (nLeadingZeros < input.length() && input.charAt(nLeadingZeros) == BASE58[0]) { + nLeadingZeros++; + } + long acc = 0; + int nDigits = 0; + int p = nLeadingZeros; + while (p < input.length()) { + int v = BASE58_VALUES[input.charAt(p) & 0xff]; + if (v >= 0) { + acc *= 58; + acc += v; + nDigits++; + if (nDigits == BASE58_CHUNK_DIGITS) { + resultNum = resultNum.multiply(BASE58_CHUNK_MOD).add(BigInteger.valueOf(acc)); + acc = 0; + nDigits = 0; + } + p++; + } else { + break; + } + } + if (nDigits > 0) { + long mul = 58; + while (--nDigits > 0) { + mul *= 58; + } + resultNum = resultNum.multiply(BigInteger.valueOf(mul)).add(BigInteger.valueOf(acc)); + } + final int BASE58_SPACE = -2; + while (p < input.length() && BASE58_VALUES[input.charAt(p) & 0xff] == BASE58_SPACE) { + p++; + } + if (p < input.length()) { + return null; + } + byte[] plainNumber = resultNum.toByteArray(); + int plainNumbersOffs = plainNumber[0] == 0 ? 1 : 0; + byte[] result = new byte[nLeadingZeros + plainNumber.length - plainNumbersOffs]; + System.arraycopy(plainNumber, plainNumbersOffs, result, nLeadingZeros, plainNumber.length - plainNumbersOffs); + return result; + } + + public static String encodeBase58(byte[] input) { + if (input == null) { + return null; + } + StringBuilder str = new StringBuilder((input.length * 350) / 256 + 1); + BigInteger bn = new BigInteger(1, input); + long rem; + while (true) { + BigInteger[] divideAndRemainder = bn.divideAndRemainder(BASE58_CHUNK_MOD); + bn = divideAndRemainder[0]; + rem = divideAndRemainder[1].longValue(); + if (bn.compareTo(BigInteger.ZERO) == 0) { + break; + } + for (int i = 0; i < BASE58_CHUNK_DIGITS; i++) { + str.append(BASE58[(int) (rem % 58)]); + rem /= 58; + } + } + while (rem != 0) { + str.append(BASE58[(int) (rem % 58)]); + rem /= 58; + } + str.reverse(); + int nLeadingZeros = 0; + while (nLeadingZeros < input.length && input[nLeadingZeros] == 0) { + str.insert(0, BASE58[0]); + nLeadingZeros++; + } + return str.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java new file mode 100644 index 0000000000..64613e1605 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -0,0 +1,78 @@ +package com.tangem.domain.wallet.xrp; + +import android.os.Bundle; +import android.util.Log; + +import com.tangem.domain.wallet.CoinData; +import com.tangem.domain.wallet.CoinEngine; + +import java.math.BigDecimal; + +public class XrpData extends CoinData { + public XrpData() { + super(); + } + + private Long balanceConfirmed, balanceUnconfirmed, sequence; + + @Override + public void loadFromBundle(Bundle B) { + super.loadFromBundle(B); + + if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); + else balanceConfirmed = null; + if (B.containsKey("BalanceUnconfirmed")) balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); + else balanceUnconfirmed = null; + if (B.containsKey("Sequence")) sequence = B.getLong("Sequence"); + } + + @Override + public void saveToBundle(Bundle B) { + super.saveToBundle(B); + try { + if (balanceConfirmed != null) B.putLong("BalanceConfirmed", balanceConfirmed); + if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed); + if (sequence != null) B.putLong("Sequence", sequence); + } catch (Exception e) { + Log.e("Can't save to bundle ", e.getMessage()); + } + } + + @Override + public void clearInfo() { + super.clearInfo(); + balanceConfirmed = null; + balanceUnconfirmed = null; + sequence = null; + } + + // balanceUnconfirmed is just the latest balance, it equals balanceConfirmed if no unconfirmed transaction present + public CoinEngine.InternalAmount getBalanceInInternalUnits() { + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed), "Drops"); + } + +// public Long getBalanceUnconfirmed() { +// return balanceUnconfirmed; +// } + + public void setBalanceConfirmed(Long balance) { + this.balanceConfirmed = balance; + } + + public void setBalanceUnconfirmed(Long balance) { + this.balanceUnconfirmed = balance; + } + + public void setSequence(Long sequence) { + this.sequence = sequence; + } + + public boolean hasBalanceInfo() { + return balanceConfirmed != null || balanceUnconfirmed != null; + } + + public boolean hasUnconfirmed() { + return !balanceConfirmed.equals(balanceUnconfirmed); + } + +} diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java new file mode 100644 index 0000000000..53ef3e3162 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -0,0 +1,411 @@ +package com.tangem.domain.wallet.xrp; + +import android.net.Uri; +import android.text.InputFilter; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.types.known.tx.signed.SignedTransaction; +import com.ripple.core.types.known.tx.txns.Payment; +import com.tangem.card_common.data.TangemCard; +import com.tangem.card_common.reader.CardProtocol; +import com.tangem.card_common.tasks.SignTask; +import com.tangem.card_common.util.Util; +import com.tangem.domain.wallet.BTCUtils; +import com.tangem.domain.wallet.BalanceValidator; +import com.tangem.domain.wallet.CoinData; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.TangemContext; +import com.tangem.util.CryptoUtil; +import com.tangem.util.DecimalDigitsInputFilter; +import com.tangem.wallet.R; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.Arrays; + +public class XrpEngine extends CoinEngine { + + private static final String TAG = XrpEngine.class.getSimpleName(); + + public XrpData coinData = null; + + public XrpEngine(TangemContext context) throws Exception { + super(context); + if (context.getCoinData() == null) { + coinData = new XrpData(); + context.setCoinData(coinData); + } else if (context.getCoinData() instanceof XrpData) { + coinData = (XrpData) context.getCoinData(); + } else { + throw new Exception("Invalid type of Blockchain data for XrpEngine"); + } + } + + public XrpEngine() { + super(); + } + + private static int getDecimals() { + return 6; + } + + private void checkBlockchainDataExists() throws Exception { + if (coinData == null) throw new Exception("No blockchain data"); + } + + @Override + public boolean awaitingConfirmation() { + if (coinData == null) return false; + return coinData.hasUnconfirmed(); + } + + @Override + public String getBalanceHTML() { + Amount balance = getBalance(); + if (balance != null) { + return balance.toDescriptionString(getDecimals()); + } else { + return ""; + } + } + + @Override + public String getBalanceCurrency() { + return "XRP"; + } + + @Override + public String getOfflineBalanceHTML() { + InternalAmount offlineInternalAmount = convertToInternalAmount(ctx.getCard().getOfflineBalance()); + Amount offlineAmount = convertToAmount(offlineInternalAmount); + return offlineAmount.toDescriptionString(getDecimals()); + } + + @Override + public boolean isBalanceNotZero() { + if (coinData == null) return false; + if (coinData.getBalanceInInternalUnits() == null) return false; + return coinData.getBalanceInInternalUnits().notZero(); + } + + @Override + public boolean hasBalanceInfo() { + if (coinData == null) return false; + return coinData.hasBalanceInfo(); + } + + public boolean isExtractPossible() { + if (!hasBalanceInfo()) { + ctx.setMessage(R.string.cannot_obtain_data_from_blockchain); + } else if (!isBalanceNotZero()) { + ctx.setMessage(R.string.wallet_empty); + } else if (awaitingConfirmation()) { + ctx.setMessage(R.string.please_wait_while_previous); + } else { + return true; + } + return false; + } + + @Override + public String getFeeCurrency() { + return "XRP"; + } + + @Override + public boolean validateAddress(String address) { + if (address == null || address.isEmpty()) { + return false; + } + + if (address.length() < 25) { + return false; + } + + if (address.length() > 35) { + return false; + } + + if (!address.startsWith("r")) { + return false; + } + + byte[] decAddress = XrpBase58.decodeBase58(address); + + if (decAddress == null || decAddress.length == 0) { + return false; + } + + byte[] payload = new byte[21]; + System.arraycopy(decAddress, 0, payload, 0, 21); + + byte[] checksum = new byte[4]; + System.arraycopy(decAddress, 21, checksum, 0, 4); + + byte[] calcChecksum = new byte[4]; + System.arraycopy(CryptoUtil.doubleSha256(payload),0,calcChecksum,0,4); + + if (!Arrays.equals(checksum, calcChecksum)) { + return false; + } + + return true; + } + + @Override + public boolean isNeedCheckNode() { + return true; + } + + @Override + public Uri getWalletExplorerUri() { + return Uri.parse("https://xrpscan.com/account/" + ctx.getCoinData().getWallet()); + } + + @Override + public InputFilter[] getAmountInputFilters() { + return new InputFilter[]{new DecimalDigitsInputFilter(getDecimals())}; + } + + @Override + public boolean checkNewTransactionAmount(Amount amount) { + if (coinData == null) return false; + if (amount.compareTo(convertToAmount(coinData.getBalanceInInternalUnits())) > 0) { + return false; + } + return true; + } + + @Override + public boolean checkNewTransactionAmountAndFee(Amount amountValue, Amount feeValue, Boolean isIncludeFee) { + InternalAmount fee; + InternalAmount amount; + + try { + checkBlockchainDataExists(); + amount = convertToInternalAmount(amountValue); + fee = convertToInternalAmount(feeValue); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + if (fee == null || amount == null) + return false; + + if (fee.isZero() || amount.isZero()) + return false; + + if (isIncludeFee && (amount.compareTo(coinData.getBalanceInInternalUnits()) > 0 || amount.compareTo(fee) < 0)) + return false; + + if (!isIncludeFee && amount.add(fee).compareTo(coinData.getBalanceInInternalUnits()) > 0) + return false; + + return true; + } + + @Override + public boolean validateBalance(BalanceValidator balanceValidator) { + try { + if (((ctx.getCard().getOfflineBalance() == null) && !ctx.getCoinData().isBalanceReceived()) || (!ctx.getCoinData().isBalanceReceived() && (ctx.getCard().getRemainingSignatures() != ctx.getCard().getMaxSignatures()))) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Unknown balance"); + balanceValidator.setSecondLine("Balance cannot be verified. Swipe down to refresh."); + return false; + } + + if (coinData.hasUnconfirmed()) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Transaction in progress"); + balanceValidator.setSecondLine("Wait for confirmation in blockchain"); + return false; + } + + if (coinData.isBalanceReceived()) {// && coinData.isBalanceEqual()) { TODO:check + balanceValidator.setScore(100); + balanceValidator.setFirstLine("Verified balance"); + balanceValidator.setSecondLine("Balance confirmed in blockchain"); + if (coinData.getBalanceInInternalUnits().isZero()) { + balanceValidator.setFirstLine("Empty wallet"); + balanceValidator.setSecondLine(""); + } + } + + if ((ctx.getCard().getOfflineBalance() != null) && !coinData.isBalanceReceived() && (ctx.getCard().getRemainingSignatures() == ctx.getCard().getMaxSignatures()) && coinData.getBalanceInInternalUnits().notZero()) { + balanceValidator.setScore(80); + balanceValidator.setFirstLine("Verified offline balance"); + balanceValidator.setSecondLine("Can't obtain balance from blockchain. Restore internet connection to be more confident. "); + } + + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + @Override + public Amount getBalance() { + if (!hasBalanceInfo()) return null; + return convertToAmount(coinData.getBalanceInInternalUnits()); + } + + @Override + public String evaluateFeeEquivalent(String fee) { + if (!coinData.getAmountEquivalentDescriptionAvailable()) return ""; + try { + Amount feeAmount = new Amount(fee, getFeeCurrency()); + return feeAmount.toEquivalentString(coinData.getRate()); + } catch (Exception e) { + return ""; + } + } + + @Override + public String getBalanceEquivalent() { + if (coinData == null || !coinData.getAmountEquivalentDescriptionAvailable()) return ""; + Amount balance = getBalance(); + if (balance == null) return ""; + return balance.toEquivalentString(coinData.getRate()); + } + + public String calculateAddress(byte[] pkCompressed) throws NoSuchAlgorithmException, NoSuchProviderException, IOException { + byte[] pkForHash = canonicalPubBytes(pkCompressed); + + ByteArrayOutputStream address = new ByteArrayOutputStream(); + address.write((byte) 0x00); + byte[] accountId = CryptoUtil.sha256ripemd160(pkForHash); + address.write(accountId); + + byte [] doubleSha256 = CryptoUtil.doubleSha256(address.toByteArray()); + address.write(Arrays.copyOfRange(doubleSha256,0,4)); + + return BTCUtils.toHex(address.toByteArray()); + } + + @Override + public Amount convertToAmount(InternalAmount internalAmount) { + BigDecimal d = internalAmount.divide(new BigDecimal("1000000")); + return new Amount(d, getBalanceCurrency()); + } + + @Override + public Amount convertToAmount(String strAmount, String currency) { + return new Amount(strAmount, currency); + } + + @Override + public InternalAmount convertToInternalAmount(Amount amount) { + BigDecimal d = amount.multiply(new BigDecimal("1000000")); + return new InternalAmount(d, "Drops"); + } + + @Override + public InternalAmount convertToInternalAmount(byte[] bytes) { + if (bytes == null) return null; + byte[] reversed = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; + return new InternalAmount(Util.byteArrayToLong(reversed), "Drops"); + } + + @Override + public byte[] convertToByteArray(InternalAmount internalAmount) { + byte[] bytes = Util.longToByteArray(internalAmount.longValueExact()); +// byte[] reversed = new byte[bytes.length]; TODO: check if needed +// for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; +// return reversed; + return bytes; + } + + @Override + public CoinData createCoinData() { + return new XrpData(); + } + + @Override + public String getUnspentInputsDescription() { + return ""; + } + + @Override + public void defineWallet() throws CardProtocol.TangemException { + try { + String wallet = calculateAddress(ctx.getCard().getWalletPublicKeyRar()); + ctx.getCoinData().setWallet(wallet); + } + catch (Exception e) + { + ctx.getCoinData().setWallet("ERROR"); + throw new CardProtocol.TangemException("Can't define wallet address"); + } + } + + public byte[] canonicalPubBytes(byte[] pkCompressed) { + byte[] pkForHash = new byte[33]; + + if (pkCompressed.length == 32) { + pkForHash[0] = (byte) 0xED; + System.arraycopy(pkCompressed, 0, pkForHash, 1,32); + } else { + pkForHash = pkCompressed; + } + } +} + + @Override + public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception { + checkBlockchainDataExists(); + + Payment payment = new Payment(); + + // Put `as` AccountID field Account, `Object` o + payment.as(AccountID.Account, "rGZG674DSZJfoY8abMPSgChxZTJZEhyMRm"); + payment.as(AccountID.Destination, "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK"); + payment.as(com.ripple.core.coretypes.Amount.Amount, "1000000000"); + payment.as(UInt32.Sequence, 10); + payment.as(com.ripple.core.coretypes.Amount.Fee, "10000"); + + SignedTransaction signedTx = payment.prepare(canonicalPubBytes(ctx.getCard().getWalletPublicKeyRar())); + + return new SignTask.TransactionToSign() { + + @Override + public boolean isSigningMethodSupported(TangemCard.SigningMethod signingMethod) { + return signingMethod == TangemCard.SigningMethod.Sign_Hash; + } + + @Override + public byte[][] getHashesToSign() { + byte[][] dataForSign = new byte[1][]; + dataForSign[0] = signedTx.signingData; + return dataForSign; + } + + @Override + public byte[] getRawDataToSign() throws Exception { + throw new Exception("Signing of raw transaction not supported for " + this.getClass().getSimpleName()); + } + + @Override + public String getHashAlgToSign() throws Exception { + throw new Exception("Signing of raw transaction not supported for " + this.getClass().getSimpleName()); + } + + @Override + public byte[] getIssuerTransactionSignature(byte[] dataToSignByIssuer) throws Exception { + throw new Exception("Transaction validation by issuer not supported in this version"); + } + + @Override + public byte[] onSignCompleted(byte[] signFromCard) { + signedTx.addSign(signFromCard); + return BTCUtils.fromHex(signedTx.tx_blob); + } + }; + } +} diff --git a/ripple-core/.gitignore b/ripple-core/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/ripple-core/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ripple-core/README.md b/ripple-core/README.md new file mode 100644 index 0000000000..d89d96f5e8 --- /dev/null +++ b/ripple-core/README.md @@ -0,0 +1,391 @@ +# SerializedTypes Overview + +Ripple uses a node store, where objects are keyed by a 32byte hash value. + +These keys are created by hashing a binary representation of the whole object +prefixed with a name-spacing sequence of bytes, unique to each class of object. +As such, a method of consistently producing a binary sequence from a given +object was required. + +Objects have fields, which are a pairing of a type and a name. Names are simply +ordinals used to look up preassigned names in a per type table. The type ordinal, +similarly, is used to lookup a given class. + +In ripple-lib-java the type equates to a `SerializedType`, with types such as 32 +bit unsigned integer, variable length byte strings and even arrays of objects. +The fields have an ordinal quality, and can be deterministically sorted, +important for consistent binary representation. + +There are also container types: An STObject, short for `SerializedType Object`, +is an associative container of fields to other SerializedTypes (even an STObject +itself). An STArray is an array of STObjects with a single Field, mapped to an +STObject, containing an arbitrary amount of Field -> SerializedType pairs. (See +notes below on differences to C++ implementation) + +## Types + +Following is a survey of some of the classes, sorted somewhat topologically. + +The following json representation of metadata related to a finalized transaction +can be used as a concrete example and will be referenced later. + +```java +/** + * + * # Transaction Meta JSON + * + * { + * "TransactionResult": "tesSUCCESS", + * + * {@link com.ripple.core.types.known.tx.result.TransactionResult} + * {@link com.ripple.core.fields.Field.TransactionResult} + * {@link com.ripple.core.coretypes.uint.UInt8} + * + * "TransactionIndex": 0, + * + * {@link com.ripple.core.types.known.tx.result.TransactionMeta#transactionIndex} + * {@link com.ripple.core.coretypes.uint.UInt32} + * + * "AffectedNodes": [ + * + * {@link com.ripple.core.types.known.tx.result.TransactionMeta#affectedNodes} + * + * { + + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + + * + * "NewFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "Sequence": 103929, + * + * {@link com.ripple.core.fields.Field#Sequence} + * + * + * "TakerGets": { + * + * {@link com.ripple.core.coretypes.Amount} + * + * "currency": "ILS", + * + * {@link com.ripple.core.coretypes.Currency} + * + * "value": "1694.768", + * + * {@link com.ripple.core.coretypes.AccountID} + * + * "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" + * + * {@link java.math.BigDecimal} + * + * }, + * + * + * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * + * {@link com.ripple.core.coretypes.AccountID} + * + * "BookDirectory": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} + * + * "TakerPays": "98957503520", + * + * {@link com.ripple.core.coretypes.Amount} + * {@link com.ripple.core.coretypes.Amount#isNative()} + * + * "OwnerNode": "000000000000000E" + * + * {@link com.ripple.core.types.known.sle.entries.Offer#ownerNodeDirectoryIndex} + * }, + * + * "LedgerIndex": "3596CE72C902BAFAAB56CC486ACAF9B4AFC67CF7CADBB81A4AA9CBDC8C5CB1AA", + * + * {@link com.ripple.core.coretypes.hash.Hash256#index} + * + * "LedgerEntryType": "Offer" + * + * {@link com.ripple.core.serialized.enums.LedgerEntryType} + * {@link com.ripple.core.types.known.sle.entries.Offer} + * } + * }, + * + * + * { + + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + + * + * "NewFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "RootIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * com.ripple.core.coretypes.hash.Hash256#index + * + * "TakerGetsIssuer": "92D705968936C419CE614BF264B5EEB1CEA47FF4", + * + * {@link com.ripple.core.coretypes.Currency} + * {@link com.ripple.core.coretypes.hash.Hash160} + * {@link com.ripple.core.fields.Field#TakerGetsIssuer} + * + * "ExchangeRate": "5C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} + * + * "TakerGetsCurrency": "000000000000000000000000494C530000000000" + * + * {@link com.ripple.core.coretypes.Currency} + * {@link com.ripple.core.coretypes.hash.Hash160} + * {@link com.ripple.core.fields.Field#TakerGetsCurrency} + * + * }, + * + * "LedgerIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.hash.Hash256#index} + * + * "LedgerEntryType": "DirectoryNode" + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode} + * {@link com.ripple.core.serialized.enums.LedgerEntryType#DirectoryNode} + * } + * }, + * + * { + * "ModifiedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} + * + * "FinalFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "RootIndex": "801C5AFB5862D4666D0DF8E5BE1385DC9B421ED09A4269542A07BC0267584B64", + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#rootIndex} + * + * "Flags": 0, + * "Owner": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * + * {@link com.ripple.core.coretypes.hash.Index#ownerDirectory} + * + * "IndexPrevious": "0000000000000000" + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#hasPreviousIndex} + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#prevIndex} + * }, + * + * "LedgerIndex": "AB03F8AA02FFA4635E7CE2850416AEC5542910A2B4DBE93C318FEB08375E0DB5", + * + * "LedgerEntryType": "DirectoryNode" + * } + * }, + * { + * "ModifiedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} + * + * "FinalFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "Sequence": 103930, + * "Flags": 0, + * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * "OwnerCount": 9, + * "Balance": "106861218302" + * + * {@link com.ripple.core.coretypes.Amount} + * }, + * + * "LedgerIndex": "CF23A37E39A571A0F22EC3E97EB0169936B520C3088963F16C5EE4AC59130B1B", + * + * {@link com.ripple.core.coretypes.hash.Index#accountRoot} + * + * "LedgerEntryType": "AccountRoot", + * + * {@link com.ripple.core.types.known.sle.entries.AccountRoot} + * {@link com.ripple.core.serialized.enums.LedgerEntryType#AccountRoot} + * + * "PreviousFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsPrevious()} + * + * "Sequence": 103929, + * "OwnerCount": 8, + * "Balance": "106861218312" + * }, + * + * "PreviousTxnID": "DE15F43F4A73C4F6CB1C334D9E47BDE84467C0902796BB81D4924885D1C11E6D", + * + * {@link com.ripple.core.types.known.tx.Transaction#hash} + * + * "PreviousTxnLgrSeq": 3225338 + * + * {@link com.ripple.core.coretypes.uint.UInt32} + * } + * } + * ] + * } +*/ +``` + +* Note that ALL field names are, by convention, upper case (in fact field names (index, hash) may be +lower cased but are not serialized) + +* The `AffectedNodes` is an STArray. As stated, the immediate +children each contain only a single key (or [Field](src/main/java/com/ripple/core/fields/Field.java#L138-L140)) + + * ModifiedNode + +Moving on. + +``` +com +└── ripple + ├── serialized + ├── core + │ + ├── enums + │   ├── LedgerEntryType + │   ├── EngineResult + │   └── TransactionType +``` + +* In the json above look at the [TransactionResult](src/main/java/com/ripple/core/fields/Field.java#L164) field. + Note that it has a Type of of UINT8, yet clearly it's represented in json as a string. + +#### com.ripple.core.fields.Type + + This is a simple Java enum(eration) of the various types. eg. + + UINT32(2) + + This definition implies giving the static ordinal `2` to the UINT32 type. + +#### com.ripple.core.fields.Field + + Consider the following definition of a field + + QualityIn(20, Type.UINT32) + + As stated before a Field has name and type ordinals, but it also has an + implied symbolic string representation (as seen used in the json above) + + The string name can be looked up via a `code`, which is an integer created by + shifting the type ordinal 16 bits to the left and ORing it with the name. + + See: [com.ripple.core.fields.Field#fromCode](src/main/java/com/ripple/core/fields/Field.java) + +#### com.ripple.core.fields.HasField + + This is simply an interface for returning a Field. We know that a Field + implies a Type and a name and there's a set amount of them. For each concrete + class implementation of a given Type, we create a XXXfield class that + implements HasField + + eg. + + ```java + protected abstract static class STArrayField implements HasField{} + public static STArrayField starrayField(final Field f) { + return new STArrayField(){ @Override public Field getField() {return f;}}; + } + ``` + + Then we can create static members on the concrete class + + ```java + static public STArrayField AffectedNodes = starrayField(Field.AffectedNodes); + static public STArrayField Signatures = starrayField(Field.Signatures); + static public STArrayField Template = starrayField(Field.Template); + ``` + + Later this is used create an api that looks as so + + ```java + if (transactionType() == TransactionType.Payment && meta.has(STArray.AffectedNodes)) { + STArray affected = meta.get(STArray.AffectedNodes); + for (STObject node : affected) { + if (node.has(STObject.CreatedNode)) { + STObject created = node.get(STObject.CreatedNode); + ``` + + This is implemented by overloading get() + + ```java + public STArray get(STArray.STArrayField f) { + return (STArray) fields.get(f.getField()); + } + ``` + +### com.ripple.core.serialized + +#### com.ripple.core.serialized.SerializedType + +```java +public interface SerializedType { + Object toJSON(); + byte[] toBytes(); + String toHex(); + void toBytesSink(BytesSink to); + Type type(); +} +``` + +#### com.ripple.core.serialized.BytesList + +A dynamic array of byte[]. Used by TypeTranslators to avoid needless +copying (see fromParser(parser, hint)). + +#### com.ripple.core.serialized.BinaryParser + +Responsible for decoding Fields and VL encoded structures. + +#### com.ripple.core.serialized.TypeTranslator + +Handles converting a SerializedType instances to/from json, binary and other non +SerializedType values. + +Has methods like fromHex, fromBytes, which delegate to fromParser. + +#### com.ripple.core.serialized.BinarySerializer + +Responsible for encoding Fields/SerializeType into binary. + +## Notes + +* In the C++ implementation of serialized objects, an STObject can, itself, be + assigned a Field, which is stored outside of the associative structure. + + This is problematic when storing as json. Consider this pseudocode. + + ```python + >>> so = STObject() + >>> so.name = "FieldName" + >>> so["FieldOfDreams"] = "A Kevin Costner Movie" + >>> sa = STArray([so]) + ``` + + How could `sa` be declared as json? + + ```json + >>> [{"FieldName" : {"FieldOfDreams": "A Kevin Costner Movie"}}] + ``` + + This is in fact how rippled works. There is no 1:1 mapping of STObject to {} + + In ripple-lib(-java)? there is, and single key children of STArrays are enforced. + +* Ripple uses 32 byte hashes for object indexes, taking half of a SHA512 hash, + which is ~%33 faster than SHA256. + +* Simply using google protocol buffers was considered inadequate [link](https://github.com/ripple/rippled/blob/ee51968820fc41c5aeadf2067bfdae54ff21fa66/BinaryFormats.txt#L16) \ No newline at end of file diff --git a/ripple-core/build.gradle b/ripple-core/build.gradle new file mode 100644 index 0000000000..7ee498ed2c --- /dev/null +++ b/ripple-core/build.gradle @@ -0,0 +1,52 @@ +apply plugin: 'java' +apply plugin: 'kotlin' + +description = 'ripple-core' + +version = '0.0.1-SNAPSHOT' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +dependencies { + compile 'net.i2p.crypto:eddsa:0.2.0' + compile 'org.bouncycastle:bcprov-jdk15on:1.58' + compile 'org.json:json:20171018' + compile 'com.fasterxml.jackson.core:jackson-databind:2.9.3' + testCompile 'junit:junit:4.12' + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5" +} +buildscript { + ext.kotlin_version = '1.3.0' + repositories { + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +repositories { + mavenCentral() +} +compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} +compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} + +task getDeps(type: Copy) { + from configurations.compile + into "$rootDir/jars/" +} + +kotlin { + experimental { + coroutines "enable" + } +} \ No newline at end of file diff --git a/ripple-core/src/main/java/README.java b/ripple-core/src/main/java/README.java new file mode 100644 index 0000000000..0d01f2dfc7 --- /dev/null +++ b/ripple-core/src/main/java/README.java @@ -0,0 +1,206 @@ +/** + * + * # Transaction Meta JSON + * + * { + * "TransactionResult": "tesSUCCESS", + * + * {@link com.ripple.core.types.known.tx.result.TransactionResult} + * {@link com.ripple.core.fields.Field.TransactionResult} + * {@link com.ripple.core.coretypes.uint.UInt8} + * + * "TransactionIndex": 0, + * + * {@link com.ripple.core.types.known.tx.result.TransactionMeta#transactionIndex} + * {@link com.ripple.core.coretypes.uint.UInt32} + * + * "AffectedNodes": [ + * + * {@link com.ripple.core.types.known.tx.result.TransactionMeta#affectedNodes} + * + * { + * "CreatedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isCreatedNode()} + * + * "NewFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "Sequence": 103929, + * + * {@link com.ripple.core.fields.Field#Sequence} + * + * + * "TakerGets": { + * + * {@link com.ripple.core.coretypes.Amount} + * + * "currency": "ILS", + * + * {@link com.ripple.core.coretypes.Currency} + * + * "value": "1694.768", + * + * {@link com.ripple.core.coretypes.AccountID} + * + * "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" + * + * {@link java.math.BigDecimal} + * + * }, + * + * + * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * + * {@link com.ripple.core.coretypes.AccountID} + * + * "BookDirectory": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} + * + * "TakerPays": "98957503520", + * + * {@link com.ripple.core.coretypes.Amount} + * {@link com.ripple.core.coretypes.Amount#isNative()} + * + * "OwnerNode": "000000000000000E" + * + * {@link com.ripple.core.types.known.sle.entries.Offer#ownerNodeDirectoryIndex} + * }, + * + * "LedgerIndex": "3596CE72C902BAFAAB56CC486ACAF9B4AFC67CF7CADBB81A4AA9CBDC8C5CB1AA", + * + * {@link com.ripple.core.coretypes.hash.Hash256#index} + * + * "LedgerEntryType": "Offer" + * + * {@link com.ripple.core.serialized.enums.LedgerEntryType} + * {@link com.ripple.core.types.known.sle.entries.Offer} + * } + * }, + * + * + * { + * "CreatedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isCreatedNode()} + * + * "NewFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "RootIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * com.ripple.core.coretypes.hash.Hash256#index + * + * "TakerGetsIssuer": "92D705968936C419CE614BF264B5EEB1CEA47FF4", + * + * {@link com.ripple.core.coretypes.Currency} + * {@link com.ripple.core.coretypes.hash.Hash160} + * {@link com.ripple.core.fields.Field#TakerGetsIssuer} + * + * "ExchangeRate": "5C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} + * + * "TakerGetsCurrency": "000000000000000000000000494C530000000000" + * + * {@link com.ripple.core.coretypes.Currency} + * {@link com.ripple.core.coretypes.hash.Hash160} + * {@link com.ripple.core.fields.Field#TakerGetsCurrency} + * + * }, + * + * "LedgerIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", + * + * {@link com.ripple.core.coretypes.hash.Hash256#index} + * + * "LedgerEntryType": "DirectoryNode" + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode} + * {@link com.ripple.core.serialized.enums.LedgerEntryType#DirectoryNode} + * } + * }, + * + * { + * "ModifiedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} + * + * "FinalFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "RootIndex": "801C5AFB5862D4666D0DF8E5BE1385DC9B421ED09A4269542A07BC0267584B64", + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#rootIndex} + * + * "Flags": 0, + * "Owner": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * + * {@link com.ripple.core.coretypes.hash.Index#ownerDirectory} + * + * "IndexPrevious": "0000000000000000" + * + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#hasPreviousIndex} + * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#prevIndex} + * }, + * + * "LedgerIndex": "AB03F8AA02FFA4635E7CE2850416AEC5542910A2B4DBE93C318FEB08375E0DB5", + * + * "LedgerEntryType": "DirectoryNode" + * } + * }, + * { + * "ModifiedNode": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode} + * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} + * + * "FinalFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} + * + * "Sequence": 103930, + * "Flags": 0, + * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", + * "OwnerCount": 9, + * "Balance": "106861218302" + * + * {@link com.ripple.core.coretypes.Amount} + * }, + * + * "LedgerIndex": "CF23A37E39A571A0F22EC3E97EB0169936B520C3088963F16C5EE4AC59130B1B", + * + * {@link com.ripple.core.coretypes.hash.Index#accountRoot} + * + * "LedgerEntryType": "AccountRoot", + * + * {@link com.ripple.core.types.known.sle.entries.AccountRoot} + * {@link com.ripple.core.serialized.enums.LedgerEntryType#AccountRoot} + * + * "PreviousFields": { + * + * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsPrevious()} + * + * "Sequence": 103929, + * "OwnerCount": 8, + * "Balance": "106861218312" + * }, + * + * "PreviousTxnID": "DE15F43F4A73C4F6CB1C334D9E47BDE84467C0902796BB81D4924885D1C11E6D", + * + * {@link com.ripple.core.types.known.tx.Transaction#hash} + * + * "PreviousTxnLgrSeq": 3225338 + * + * {@link com.ripple.core.coretypes.uint.UInt32} + * } + * } + * ] + * } +*/ \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java b/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java new file mode 100644 index 0000000000..e46af9db43 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java @@ -0,0 +1,32 @@ +package com.ripple.core.binary; + +import com.ripple.core.serialized.StreamSink; + +import java.io.*; + +public class FileSTWriter extends STWriter implements Closeable { + BufferedOutputStream out; + + private FileSTWriter(StreamSink sink, BufferedOutputStream out) { + super(sink); + this.out = out; + } + + public static FileSTWriter fromFile(String path) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(path); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + BufferedOutputStream out = new BufferedOutputStream(fos); + StreamSink sink = new StreamSink(out); + + return new FileSTWriter(sink, out); + } + + @Override + public void close() throws IOException { + out.close(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/binary/STReader.java b/ripple-core/src/main/java/com/ripple/core/binary/STReader.java new file mode 100644 index 0000000000..dc3655073b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/binary/STReader.java @@ -0,0 +1,126 @@ +package com.ripple.core.binary; + +import com.ripple.core.coretypes.*; +import com.ripple.core.coretypes.hash.Hash128; +import com.ripple.core.coretypes.hash.Hash160; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.uint.UInt16; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.StreamBinaryParser; +import com.ripple.core.types.known.sle.LedgerEntry; +import com.ripple.core.types.known.tx.Transaction; +import com.ripple.core.types.known.tx.result.TransactionMeta; +import com.ripple.core.types.known.tx.result.TransactionResult; + +import java.util.Arrays; +import java.util.Date; + +public class STReader { + protected BinaryParser parser; + public STReader(BinaryParser parser) { + this.parser = parser; + } + public STReader(String hex) { + this.parser = new BinaryParser(hex); + } + + public static STReader fromFile(String arg) { + return new STReader(StreamBinaryParser.fromFile(arg)); + } + + public UInt8 uInt8() { + return UInt8.fromParser(parser); + } + public UInt16 uInt16() { + return UInt16.fromParser(parser); + } + public UInt32 uInt32() { + return UInt32.fromParser(parser); + } + public UInt64 uInt64() { + return UInt64.fromParser(parser); + } + public Hash128 hash128() { + return Hash128.fromParser(parser); + } + public Hash160 hash160() { + return Hash160.fromParser(parser); + } + public Currency currency() { + return Currency.fromParser(parser); + } + public Hash256 hash256() { + return Hash256.fromParser(parser); + } + public Vector256 vector256() { + return Vector256.fromParser(parser); + } + public AccountID accountID() { + return AccountID.fromParser(parser); + } + public Blob variableLength() { + int hint = parser.readVLLength(); + return Blob.fromParser(parser, hint); + } + public Amount amount() { + return Amount.fromParser(parser); + } + public PathSet pathSet() { + return PathSet.fromParser(parser); + } + + public STObject stObject() { + return STObject.fromParser(parser); + } + public STObject vlStObject() { + return STObject.fromParser(parser, parser.readVLLength()); + } + + public HashPrefix hashPrefix() { + byte[] read = parser.read(4); + for (HashPrefix hashPrefix : HashPrefix.values()) { + if (Arrays.equals(read, hashPrefix.bytes())) { + return hashPrefix; + } + } + return null; + } + + public STArray stArray() { + return STArray.fromParser(parser); + } + public Date rippleDate() { + return RippleDate.fromParser(parser); + } + + public BinaryParser parser() { + return parser; + } + + public TransactionResult readTransactionResult(UInt32 ledgerIndex) { + Hash256 hash = hash256(); + Transaction txn = (Transaction) vlStObject(); + TransactionMeta meta = (TransactionMeta) vlStObject(); + return new TransactionResult(ledgerIndex.longValue(), hash, txn, meta); + } + + public LedgerEntry readLE() { + Hash256 index = hash256(); + STObject object = vlStObject(); + LedgerEntry le = (LedgerEntry) object; + le.index(index); + return le; + } + + public int readOneInt() { + return parser.readOneInt(); + } + + public boolean end() { + return parser.end(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java b/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java new file mode 100644 index 0000000000..77f28eb7f7 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java @@ -0,0 +1,71 @@ +package com.ripple.core.binary; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.serialized.BinarySerializer; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.StreamSink; +import com.ripple.core.types.known.sle.LedgerEntry; +import com.ripple.core.types.known.tx.result.TransactionResult; + +import java.io.*; + +public class STWriter implements BytesSink, Closeable { + BytesSink sink; + BinarySerializer serializer; + public STWriter(BytesSink bytesSink) { + serializer = new BinarySerializer(bytesSink); + sink = bytesSink; + } + + private OutputStream stream; + private STWriter(BytesSink sink, OutputStream stream) { + this(sink); + this.stream = stream; + } + + public static STWriter toFile(String path) { + try { + FileOutputStream fos = new FileOutputStream(path); + BufferedOutputStream bos = new BufferedOutputStream(fos); + return new STWriter(new StreamSink(bos), bos); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + public void write(SerializedType obj) { + obj.toBytesSink(sink); + } + public void writeVl(SerializedType obj) { + serializer.addLengthEncoded(obj); + } + + @Override + public void add(byte aByte) { + sink.add(aByte); + } + + @Override + public void add(byte[] bytes) { + sink.add(bytes); + } + + public void write(TransactionResult result) { + write(result.hash); + writeVl(result.txn); + writeVl(result.meta); + } + + public void write(Hash256 hash256, LedgerEntry le) { + write(hash256); + writeVl(le); + } + + @Override + public void close() throws IOException { + if (this.stream != null) { + this.stream.close(); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java b/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java new file mode 100644 index 0000000000..55552ede01 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java @@ -0,0 +1,110 @@ +package com.ripple.core.cache; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.types.known.sle.LedgerEntry; +import com.ripple.core.types.known.tx.result.AffectedNode; +import com.ripple.core.types.known.tx.result.TransactionMeta; +import com.ripple.core.types.known.tx.result.TransactionResult; + +import java.util.TreeMap; + +public class SLECache { + private final TreeMap cache = new TreeMap(); + + public static class CacheEntry { + public LedgerEntry le; + public UInt32 prevTxnIndex; + public UInt32 prevLedger; + public boolean deleted = false; + + public void upateLedgerEntry(LedgerEntry le, UInt32 ledgerIndex, UInt32 txnIndex) { + if (doUpdate(txnIndex, ledgerIndex)) { + // in the first case + prevTxnIndex = txnIndex; + prevLedger = ledgerIndex; + + if (le == null) { + deleted = true; + } + this.le = le; + } + } + + private boolean doUpdate(UInt32 txnIndex, UInt32 ledgerIndex) { + if (le == null && !deleted) { + return true; + } + if (prevLedger == null) { + return true; + } + int ledgerCmp = ledgerIndex.compareTo(prevLedger); + if (ledgerCmp == 1) { + return true; + } + if (ledgerCmp == 0) { + if (prevTxnIndex == null) { + // We don't know, should log a warning or something + // Should we keep the first one that we have of this index + // or can we assume that the latest is the best? + return true; + } + if (txnIndex.compareTo(prevTxnIndex) == 1) { + // This happened AFTER + return true; + } + } + //ledgerCmp == -1 or txnIndex <= previousTxnIndex ss + return false; + } + } + + public boolean cache(LedgerEntry le, UInt32 validatedLedgerIndex) { + Hash256 index = le.ledgerIndex(); + CacheEntry ce = getOrCreate(index); + ce.upateLedgerEntry(le, validatedLedgerIndex, null); + return true; + } + + private CacheEntry getEntry(Hash256 index) { + return cache.get(index); + } + + private CacheEntry createEntry(Hash256 index) { + CacheEntry ce = new CacheEntry(); + cache.put(index, ce); + return ce; + } + + public LedgerEntry get(Hash256 index) { + CacheEntry entry = getEntry(index); + return entry == null || entry.deleted ? null : entry.le; + } + + public void updateFromTransactionResult(TransactionResult tr) { + if (!tr.validated) { + return; + } + + TransactionMeta meta = tr.meta; + UInt32 ledgerIndex = tr.ledgerIndex; + UInt32 txnIndex = meta.transactionIndex(); + + for (AffectedNode an : meta.affectedNodes()) { + Hash256 index = an.ledgerIndex(); + CacheEntry ce = getOrCreate(index); + ce.upateLedgerEntry(an.isDeletedNode() ? null : (LedgerEntry) an.nodeAsFinal(), + ledgerIndex, + txnIndex); + } + } + + private CacheEntry getOrCreate(Hash256 index) { + CacheEntry already = getEntry(index); + if (already == null) { + return createEntry(index); + } else { + return already; + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java b/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java new file mode 100644 index 0000000000..606c5b2b71 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java @@ -0,0 +1,188 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.coretypes.hash.Hash160; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.AccountIDField; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.crypto.Seed; +import com.ripple.crypto.keys.IKeyPair; +import com.ripple.encodings.addresses.Addresses; +import com.ripple.encodings.common.B16; +import com.ripple.utils.Utils; + +/** + * Originally it was intended that AccountIDs would be variable length so that's + * why they are variable length encoded as top level field objects. + * + * Note however, that in practice, all account ids are just 160 bit hashes. + * Consider the fields TakerPaysIssuer and fixed length encoding of issuers in + * amount serializations. + * + * Thus, we extend Hash160 which affords us some functionality. + */ +public class AccountID extends Hash160 { + public static final AccountID NEUTRAL = fromInteger(1); + public static final AccountID XRP_ISSUER = fromInteger(0); + + public final String address; + + public AccountID(byte[] bytes) { + this(bytes, encodeAddress(bytes)); + } + + public AccountID(byte[] bytes, String address) { + super(bytes); + this.address = address; + } + + // Static from* constructors + public static AccountID fromString(String value) { + if (value.length() == 160 / 4) { + return fromBytes(B16.decode(value)); + } else { + return fromAddress(value); + } + } + + static public AccountID fromAddress(String address) { + byte[] bytes = Addresses.decodeAccountID(address); + return new AccountID(bytes, address); + } + + static public AccountID fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + static public AccountID fromHex(String hex) { + return translate.fromHex(hex); + } + + public static AccountID fromKeyPair(IKeyPair kp) { + byte[] bytes = kp.id(); + return new AccountID(bytes, encodeAddress(bytes)); + } + + public static AccountID fromPassPhrase(String phrase) { + return fromKeyPair(Seed.fromPassPhrase(phrase).keyPair()); + } + + static public AccountID fromSeed(String seed) { + return fromKeyPair(Seed.getKeyPair(seed)); + } + + private static AccountID fromInteger(Integer n) { + return fromBytes(Utils.padTo160(new UInt32(n).toByteArray())); + } + + public static AccountID fromBytes(byte[] bytes) { + return new AccountID(bytes, encodeAddress(bytes)); + } + + @Override + public int hashCode() { + return address.hashCode(); + } + + @Override + public String toString() { + return address; + } + + public Issue issue(String code) { + return new Issue(Currency.fromString(code), this); + } + + public Issue issue(Currency c) { + return new Issue(c, this); + } + + public boolean isNativeIssuer() { + return this == XRP_ISSUER || equals(XRP_ISSUER); + } + + // SerializedType interface implementation + @Override + public Object toJSON() { + return toString(); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + to.add(bytes()); + } + + @Override + public Type type() { + return Type.AccountID; + } + + public Hash256 lineIndex(Issue issue) { + if (issue.isNative()) throw new AssertionError(); + return Index.rippleState(this, issue.issuer(), issue.currency()); + } + + public static class Translator extends TypeTranslator { + @Override + public AccountID fromParser(BinaryParser parser, Integer hint) { + if (hint == null) { + hint = 20; + } + return AccountID.fromBytes(parser.read(hint)); + } + + @Override + public String toString(AccountID obj) { + return obj.toString(); + } + + @Override + public AccountID fromString(String value) { + return AccountID.fromString(value); + } + } + + // + + static public Translator translate = new Translator(); + + // helpers + + private static String encodeAddress(byte[] address) { + return Addresses.encodeAccountID(address); + } + + // Typed field definitions + private static AccountIDField accountField(final Field f) { + return new AccountIDField() { + @Override + public Field getField() { + return f; + } + }; + } + + static public AccountIDField Account = accountField(Field.Account); + static public AccountIDField Owner = accountField(Field.Owner); + static public AccountIDField Destination = accountField(Field.Destination); + static public AccountIDField Issuer = accountField(Field.Issuer); + static public AccountIDField Target = accountField(Field.Target); + static public AccountIDField RegularKey = accountField(Field.RegularKey); + static public AccountIDField Authorize = accountField(Field.Authorize); + static public AccountIDField Unauthorize = accountField(Field.Unauthorize); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java new file mode 100644 index 0000000000..3813a5ac09 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java @@ -0,0 +1,790 @@ +package com.ripple.core.coretypes; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.fields.AmountField; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import org.json.JSONObject; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.Objects; + +/** + * In ripple, amounts are either XRP, the native currency, or an IOU of + * a given currency as issued by a designated account. + */ +public class Amount extends Number implements SerializedType, Comparable + +{ + + private static BigDecimal TAKER_PAYS_FOR_THAT_DAMN_OFFER = new BigDecimal("1000000000000.000100"); + +// public static final Amount NEUTRAL_ZERO = new Amount(Currency.NEUTRAL, AccountID.NEUTRAL); + + /** + * Thrown when an Amount is constructed with an invalid value + */ + public static class PrecisionError extends RuntimeException { + public Amount illegal; + + public PrecisionError(String s) { + super(s); + } + + public PrecisionError(String s, Amount amount) { + super(s); + illegal = amount; + } + } + + // For rounding/multiplying/dividing + public static final MathContext MATH_CONTEXT = new MathContext(16, RoundingMode.HALF_UP); + // The maximum amount of digits in mantissa of an IOU amount + public static final int MAXIMUM_IOU_PRECISION = 16; + // The smallest quantity of an XRP is a drop, 1 millionth of an XRP + public static final int MAXIMUM_NATIVE_SCALE = 6; + // Defines bounds for native amounts + public static final BigDecimal MAX_NATIVE_VALUE = parseDecimal("100,000,000,000.0"); + public static final BigDecimal MIN_NATIVE_VALUE = parseDecimal("0.000,001"); + + // These are flags used when serializing to binary form + public static final UInt64 BINARY_FLAG_IS_IOU = new UInt64("8000000000000000", 16); + public static final UInt64 BINARY_FLAG_IS_NON_NEGATIVE_NATIVE = new UInt64("4000000000000000", 16); + + public static final Amount ONE_XRP = fromString("1.0"); + + // TODO, even though all these fields are effectively final, and only + // ever set it would be nice to actually use the final modifier. + // Perhaps create an amount builder. + + // The quantity of XRP or Issue(currency/issuer pairing) + // When native, the value unit is XRP, not drops. + private BigDecimal value; + private Currency currency; + // If the currency is XRP + private boolean isNative; + // Normally, in the constructor of an Amount the value is checked + // that it's scale/precision and quantity are correctly bounded. + // If unbounded is true, these checks are skipped. + // This is there for historical ledgers that contain amounts that + // would now be considered malformed (in the sense of the transaction + // engine result class temMALFORMED) + private boolean unbounded = false; + // The ZERO account is used for specifying the issuer for native + // amounts. In practice the issuer is never used when an + // amount is native. + private AccountID issuer; + + private UInt64 mantissa; + // The exponent is always calculated. + private int exponent; + + public Amount(BigDecimal value, Currency currency, AccountID issuer) { + this(value, currency, issuer, false); + } + + public Amount(BigDecimal xrpScaleValue) { + isNative = true; + currency = Currency.XRP; + this.setAndCheckValue(xrpScaleValue); + } + + public Amount(Number xrpScaleValue) { + isNative = true; + currency = Currency.XRP; + this.setAndCheckValue(BigDecimal.valueOf(xrpScaleValue.doubleValue())); + } + + public Amount(BigDecimal value, Currency currency, AccountID issuer, boolean isNative, boolean unbounded) { + this.isNative = isNative; + this.currency = currency; + this.unbounded = unbounded; + this.setAndCheckValue(value); + // done AFTER set value which sets some default values + this.issuer = issuer; + } + + public Amount(Currency currency, AccountID account) { + this(BigDecimal.ZERO, currency, account); + } + + // Private constructors + Amount(BigDecimal newValue, Currency currency, AccountID issuer, boolean isNative) { + this(newValue, currency, issuer, isNative, false); + } + + private Amount(BigDecimal value, String currency, String issuer) { + this(value, currency); + if (issuer != null) { + this.issuer = AccountID.fromString(issuer); + } + } + + public Amount(BigDecimal value, String currency) { + isNative = false; + this.currency = Currency.fromString(currency); + this.setAndCheckValue(value); + } + + private void setAndCheckValue(BigDecimal value) { + this.value = value.stripTrailingZeros(); + initialize(); + } + + private void initialize() { + if (isNative()) { + issuer = AccountID.XRP_ISSUER; + if (!unbounded) { + checkXRPBounds(); + } + // Offset is unused for native amounts + exponent = -6; // compared to drops. + } else { + issuer = AccountID.NEUTRAL; + exponent = calculateExponent(); + + if (value.precision() > MAXIMUM_IOU_PRECISION && !unbounded) { + String err = "value precision of " + value.precision() + + " is greater than maximum " + + "iou precision of " + MAXIMUM_IOU_PRECISION; + throw new PrecisionError(err, this); + } + } + mantissa = calculateMantissa(); + } + + private Amount newValue(BigDecimal newValue) { + return newValue(newValue, false, false); + } + + private Amount newValue(BigDecimal newValue, boolean round, boolean unbounded) { + if (round) { + newValue = roundValue(newValue, isNative); + } + return new Amount(newValue, currency, issuer, isNative, unbounded); + } + + private Amount newValue(BigDecimal val, boolean round) { + return newValue(val, round, false); + } + + /* Getters and Setters */ + + public BigDecimal value() { + return value; + } + + public Currency currency() { + return currency; + } + + public AccountID issuer() { + return issuer; + } + + public Issue issue() { + // TODO: store the currency and issuer as an Issue + return new Issue(currency, issuer); + } + + private UInt64 mantissa() { + // Having this lazily computed and then cached would give significant + // performance boosts in some single threaded contexts. Given the inputs + // for the method are at least effectively final, and the method is + // essentially a pure function, it seems probably safe to do. It + // seems at worst, that in a multi threaded context, some extra work + // will be done in rare cases? + // TODO: check this assumption + return mantissa; + } + + public int exponent() { + return exponent; + } + + public boolean isNative() { + return isNative; + } + + public String currencyString() { + return currency.toString(); + } + + public String issuerString() { + if (issuer == null) { + return ""; + } + return issuer.toString(); + } + + /* Offset & Mantissa Helpers */ + + /** + * @return a positive value for the mantissa + */ + private UInt64 calculateMantissa() { + if (isNative()) { + return new UInt64(bigIntegerDrops().abs()); + } else { + return new UInt64(bigIntegerIOUMantissa()); + } + } + + private int calculateExponent() { + return -MAXIMUM_IOU_PRECISION + value.precision() - value.scale(); + } + + private BigInteger bigIntegerIOUMantissa() { + return exactBigIntegerScaledByPowerOfTen(-exponent).abs(); + } + + private BigInteger bigIntegerDrops() { + return exactBigIntegerScaledByPowerOfTen(MAXIMUM_NATIVE_SCALE); + } + + private BigInteger exactBigIntegerScaledByPowerOfTen(int n) { + return value.scaleByPowerOfTen(n).toBigIntegerExact(); + } + + /* Equality testing */ + + private boolean equalValue(Amount amt) { + return compareTo(amt) == 0; + } + @Override + public boolean equals(Object obj) { + if (obj instanceof Amount) { + return equals((Amount) obj); + } + return super.equals(obj); + } + + public boolean equals(Amount amt) { + return equalValue(amt) && + currency.equals(amt.currency) && + (isNative() || issuer.equals(amt.issuer)); + } + + public boolean equalsExceptIssuer(Amount amt) { + return equalValue(amt) && + currencyString().equals(amt.currencyString()); + } + + public int compareTo(Amount amount) { + Objects.requireNonNull(amount); + return value.compareTo(amount.value); + } + + public boolean isZero() { + return value.signum() == 0; + } + + public boolean isNegative() { + return value.signum() == -1; + } + + // Maybe you want !isNegative() + // Any amount that !isNegative() isn't necessarily positive + // Is a zero amount strictly positive? no + public boolean isPositive() { + return value.signum() == 1; + } + + /** + + Arithmetic Operations + + There's no checking if an amount is of a different currency/issuer. + + All operations return amounts of the same currency/issuer as the + first operand. + + eg. + + amountOne.add(amountTwo) + + The currency/issuer of the resultant amount, is that of `amountOne` + + Divide and multiply are equivalent to the javascript ripple-lib + ratio_human and product_human. + + */ + public Amount add(BigDecimal augend) { + return newValue(value.add(augend), true); + } + + public Amount add(Amount augend) { + return add(augend.value); + } + + public Amount add(Number augend) { + return add(BigDecimal.valueOf(augend.doubleValue())); + } + + public Amount subtract(BigDecimal subtrahend) { + return newValue(value.subtract(subtrahend), true); + } + + public Amount subtract(Amount subtrahend) { + return subtract(subtrahend.value); + } + + public Amount subtract(Number subtrahend) { + return subtract(BigDecimal.valueOf(subtrahend.doubleValue())); + } + + public Amount multiply(BigDecimal divisor) { + return newValue(value.multiply(divisor, MATH_CONTEXT), true); + } + + public Amount multiply(Amount multiplicand) { + return multiply(multiplicand.value); + } + + public Amount multiply(Number multiplicand) { + return multiply(BigDecimal.valueOf(multiplicand.doubleValue())); + } + + public Amount divide(BigDecimal divisor) { + return newValue(value.divide(divisor, MATH_CONTEXT), true); + } + + public Amount divide(Amount divisor) { + return divide(divisor.value); + } + + public Amount divide(Number divisor) { + return divide(BigDecimal.valueOf(divisor.doubleValue())); + } + + public Amount negate() { + return newValue(value.negate()); + } + + public Amount abs() { + return newValue(value.abs()); + } + public Amount min(Amount val) { + return (compareTo(val) <= 0 ? this : val); + } + public Amount max(Amount val) { + return (compareTo(val) >= 0 ? this : val); + } + + /* Offer related helpers */ + public BigDecimal computeQuality(Amount toExchangeThisWith) { + return value.divide(toExchangeThisWith.value, MathContext.DECIMAL128); + } + /** + * @return Amount + * The real native unit is a drop, one million of which are an XRP. + * We want `one` unit at XRP scale (1e6 drops), or if it's an IOU, + * just `one`. + */ + public Amount one() { + if (isNative()) { + return ONE_XRP; + } else { + return issue().amount(1); + } + } + + /* Serialized Type implementation */ + + @Override + public Object toJSON() { + if (isNative()) { + return toDropsString(); + } else { + return toJSONObject(); + } + } + + public JSONObject toJSONObject() { + if (isNative()) { + throw new RuntimeException("Native amounts must be serialized as a string"); + } + + JSONObject out = new JSONObject(); + out.put("currency", currencyString()); + out.put("value", valueText()); + out.put("issuer", issuerString()); + return out; + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + // TODO: probably better off using long + UInt64 man = mantissa(); + + if (isNative()) { + if (!isNegative()) { + man = man.or(BINARY_FLAG_IS_NON_NEGATIVE_NATIVE); + } + to.add(man.toByteArray()); + } else { + int exponent = exponent(); + UInt64 packed; + + if (isZero()) { + packed = BINARY_FLAG_IS_IOU; + } else if (isNegative()) { + packed = man.or(new UInt64(512 + /* 0 + */ 97 + exponent).shiftLeft(64 - 10)); + } else { + packed = man.or(new UInt64(512 + 256 + 97 + exponent).shiftLeft(64 - 10)); + } + + to.add(packed.toByteArray()); + to.add(currency.bytes()); + to.add(issuer.bytes()); + } + } + + @Override + public Type type() { + return Type.Amount; + } + + public static class Translator extends TypeTranslator { + @Override + public Amount fromString(String s) { + // We need to use the full dotted.path here, otherwise + // we get confused with the AmountField Amount + return com.ripple.core.coretypes.Amount.fromString(s); + } + + @Override + public Amount fromParser(BinaryParser parser, Integer hint) { + BigDecimal value; + byte[] mantissa = parser.read(8); + byte b1 = mantissa[0], b2 = mantissa[1]; + + boolean isIOU = (b1 & 0x80) != 0; + boolean isPositive = (b1 & 0x40) != 0; + int sign = isPositive ? 1 : -1; + + if (isIOU) { + mantissa[0] = 0; + Currency curr = Currency.fromParser(parser); + AccountID issuer = AccountID.fromParser(parser); + int exponent = ((b1 & 0x3F) << 2) + ((b2 & 0xff) >> 6) - 97; + mantissa[1] &= 0x3F; + + value = new BigDecimal(new BigInteger(sign, mantissa), -exponent); + return new Amount(value, curr, issuer, false); + } else { + mantissa[0] &= 0x3F; + value = xrpFromDropsMantissa(mantissa, sign); + return new Amount(value); + } + } + + @Override + public String toString(Amount obj) { + return obj.stringRepr(); + } + + public JSONObject toJSONObject(Amount obj) { + return obj.toJSONObject(); + } + + @Override + public Amount fromJSONObject(JSONObject jsonObject) { + String valueString = jsonObject.getString("value"); + String issuerString = jsonObject.getString("issuer"); + String currencyString = jsonObject.getString("currency"); + return new Amount(new BigDecimal(valueString), currencyString, issuerString); + } + + @Override + public Amount fromJacksonObject(ObjectNode object) { + checkField(object, "value"); + checkField(object, "issuer"); + checkField(object, "currency"); + String value = object.get("value").asText(); + String issuer = object.get("issuer").asText(); + String currency = object.get("currency").asText(); + return new Amount(new BigDecimal(value), currency, issuer); + } + + private void checkField(ObjectNode object, String field) { + if (!object.has(field)) { + throw new IllegalArgumentException(object + "is missing `" + + field + "`"); + } + } + } + static public Translator translate = new Translator(); + + public static BigDecimal xrpFromDropsMantissa(byte[] mantissa, int sign) { + return new BigDecimal(new BigInteger(sign, mantissa), 6); + } + + /* Number overides */ + @Override + public int intValue() { + return value.intValueExact(); + } + + @Override + public long longValue() { + return value.longValueExact(); + } + + @Override + public float floatValue() { + return value.floatValue(); + } + + @Override + public double doubleValue() { + return value.doubleValue(); + } + + public BigInteger bigIntegerValue() { + return value.toBigIntegerExact(); + } + + public Amount newIssuer(AccountID issuer) { + return new Amount(value, currency, issuer, isNative, unbounded); + } + + public Amount copy() { + return new Amount(value, currency, issuer, isNative, unbounded); + } + + // Static constructors + public static Amount fromString(String val) { + if (val.contains("/")) { + return fromIOUString(val); + } else if (val.contains(".")) { + return fromXrpString(val); + } else { + return fromDropString(val); + } + + } + + public static Amount fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static Amount fromHex(String hex) { + return translate.fromHex(hex); + } + public static Amount fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + public static Amount fromJSONObject(JSONObject jsonObject) { + return translate.fromJSONObject(jsonObject); + } + + public static Amount fromJacksonObject(ObjectNode object) { + return translate.fromJacksonObject(object); + } + + public static Amount fromValue(Object amount) { + return translate.fromValue(amount); + } + + public static Amount fromDropString(String val) { + BigDecimal xrp = new BigDecimal(val).scaleByPowerOfTen(-6); + checkDropsValueWhole(val); + return new Amount(xrp); + } + + public static Amount fromIOUString(String val) { + String[] split = val.split("/"); + if (split.length == 1) { + throw new RuntimeException("IOU string must be in the form " + + "number/currencyString or " + + "number/currencyString/issuerString"); + } else if (split.length == 2) { + return new Amount(new BigDecimal(split[0]), split[1]); + } else { + return new Amount(new BigDecimal(split[0]), split[1], split[2]); + } + } + + @Deprecated + private static Amount fromXrpString(String valueString) { + BigDecimal val = new BigDecimal(valueString); + return new Amount(val); + } + + /** + * @return A String representation as used by ripple json format + */ + public String stringRepr() { + if (isNative()) { + return toDropsString(); + } else { + return iouTextFull(); + } + } + + public String toDropsString() { + if (!isNative()) { + throw new RuntimeException("Amount is not native"); + } + return bigIntegerDrops().toString(); + } + + private String iouText() { + return String.format("%s/%s", valueText(), currencyString()); + } + + public String iouTextFull() { + return String.format("%s/%s/%s", valueText(), currencyString(), issuerString()); + } + + public String toTextFull() { + if (isNative()) { + return nativeText(); + } else { + return iouTextFull(); + } + } + + public String nativeText() { + return String.format("%s/XRP", valueText()); + } + + @Override + public String toString() { + return toTextFull(); + } + + public String toText() { + if (isNative()) { + return nativeText(); + } else { + return iouText(); + } + } + + /** + * @return A String containing the value (in XRP scale when native) + * as a decimal number + * + */ + public String valueText() { + return value.signum() == 0 ? "0" : value().toPlainString(); + } + + private void checkLowerDropBound(BigDecimal val) { + if (val.scale() > 6) { + PrecisionError bigger = getOutOfBoundsError(val, + "smaller than min native value", + MIN_NATIVE_VALUE); + bigger.illegal = this; + throw bigger; + } + } + + private void checkUpperBound(BigDecimal val) { + if (val.compareTo(MAX_NATIVE_VALUE) > 0) { + PrecisionError bigger = getOutOfBoundsError(val, + "bigger than max native value ", + MAX_NATIVE_VALUE); + bigger.illegal = this; + throw bigger; + } + } + + private static PrecisionError getOutOfBoundsError( + BigDecimal abs, + String sized, + BigDecimal bound) { + return new PrecisionError( + abs.toPlainString() + " absolute XRP is " + sized + bound); + } + + private void checkXRPBounds() { + BigDecimal v = value.abs(); + try { + checkLowerDropBound(v); + checkUpperBound(v); + } catch (PrecisionError e) { + if (v.compareTo(TAKER_PAYS_FOR_THAT_DAMN_OFFER) == 0) { + return; + } + throw e; + } + } + + + private static int significantDigits(BigDecimal input) { + input = input.stripTrailingZeros(); + return input.scale() < 0 + ? input.precision() - input.scale() + : input.precision(); + } + + public int significantDigits() { + return significantDigits(value); + } + + public static void checkDropsValueWhole(String drops) { + boolean contains = drops.contains("."); + if (contains) { + throw new RuntimeException("Drops string contains floating point is decimal"); + } + } + + public static BigDecimal roundValue(BigDecimal value, boolean nativeSrc) { + int i = value.precision() - value.scale(); + return value.setScale(nativeSrc ? MAXIMUM_NATIVE_SCALE : + MAXIMUM_IOU_PRECISION - i, + MATH_CONTEXT.getRoundingMode()); + } + + private static BigDecimal parseDecimal(String s) { + return new BigDecimal(s.replace(",", "")); //# .scaleByPowerOfTen(6); + } + + private static AmountField amountField(final Field f) { + return new AmountField() { + @Override + public Field getField() { + return f; + } + }; + } + + static public AmountField Amount = amountField(Field.Amount); + static public AmountField Balance = amountField(Field.Balance); + static public AmountField LimitAmount = amountField(Field.LimitAmount); + static public AmountField DeliveredAmount = amountField(Field.DeliveredAmount); + static public AmountField TakerPays = amountField(Field.TakerPays); + static public AmountField TakerGets = amountField(Field.TakerGets); + static public AmountField LowLimit = amountField(Field.LowLimit); + static public AmountField HighLimit = amountField(Field.HighLimit); + static public AmountField Fee = amountField(Field.Fee); + static public AmountField SendMax = amountField(Field.SendMax); + static public AmountField DeliverMin = amountField(Field.DeliverMin); + static public AmountField MinimumOffer = amountField(Field.MinimumOffer); + static public AmountField RippleEscrow = amountField(Field.RippleEscrow); + static public AmountField taker_gets_funded = amountField(Field.taker_gets_funded); + static public AmountField taker_pays_funded = amountField(Field.taker_pays_funded); + +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java new file mode 100644 index 0000000000..48708f78f5 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java @@ -0,0 +1,119 @@ + +package com.ripple.core.coretypes; + +import com.ripple.core.fields.BlobField; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; +import org.bouncycastle.util.encoders.Hex; + +public class Blob implements SerializedType { + public Blob(byte[] bytes) { + buffer = bytes.clone(); + } + + private final byte[] buffer; + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return buffer; + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.Blob; + } + + public static Blob fromBytes(byte[] bytes) { + return new Blob(bytes); + } + + public static Blob fromHex(String hex) { + return fromBytes(B16.decode(hex)); + } + + public static Blob fromParser(BinaryParser parser, int hint) { + return translate.fromParser(parser, hint); + } + public static Blob fromParser(BinaryParser parser) { + return translate.fromParser(parser, null); + } + + public static class Translator extends TypeTranslator { + @Override + public Blob fromParser(BinaryParser parser, Integer hint) { + if (hint == null) { + hint = parser.size() - parser.pos(); + } + return new Blob(parser.read(hint)); + } + + @Override + public Object toJSON(Blob obj) { + return toString(obj); + } + + @Override + public String toString(Blob obj) { + return B16.encode(obj.buffer); + } + + @Override + public Blob fromString(String value) { + return new Blob(Hex.decode(value)); + } + + @Override + public void toBytesSink(Blob obj, BytesSink to) { + to.add(obj.buffer.clone()); + } + } + + static public Translator translate = new Translator(); + + private static BlobField blobField(final Field f) { + return new BlobField() { + @Override + public Field getField() { + return f; + } + }; + } + + static public BlobField PublicKey = blobField(Field.PublicKey); + static public BlobField MessageKey = blobField(Field.MessageKey); + static public BlobField SigningPubKey = blobField(Field.SigningPubKey); + static public BlobField TxnSignature = blobField(Field.TxnSignature); + static public BlobField MasterSignature = blobField(Field.MasterSignature); + static public BlobField Signature = blobField(Field.Signature); + static public BlobField Domain = blobField(Field.Domain); + static public BlobField FundCode = blobField(Field.FundCode); + static public BlobField RemoveCode = blobField(Field.RemoveCode); + static public BlobField ExpireCode = blobField(Field.ExpireCode); + static public BlobField CreateCode = blobField(Field.CreateCode); + + static public BlobField MemoType = blobField(Field.MemoType); + static public BlobField MemoData = blobField(Field.MemoData); + static public BlobField MemoFormat = blobField(Field.MemoFormat); + static public BlobField Condition = blobField(Field.Condition); + static public BlobField Fulfillment = blobField(Field.Fulfillment); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java new file mode 100644 index 0000000000..27832e335b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java @@ -0,0 +1,250 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.coretypes.hash.Hash160; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.encodings.common.B16; +import com.ripple.utils.Utils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * Funnily enough, yes, in rippled a currency is represented by a Hash160 type. + * For the sake of consistency and convenience, this quirk is repeated here. + * + * https://gist.github.com/justmoon/8597643 + */ +public class Currency extends Hash160 { + public static final Currency NEUTRAL = new Currency(Utils.padTo160(BigInteger.ONE.toByteArray())); + public static final Currency XRP = new Currency(Utils.padTo160(BigInteger.ZERO.toByteArray())); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + public boolean isNative() { + return this == Currency.XRP || equals(Currency.XRP); + } + + public boolean isIOU() { + return !isNative(); + } + + public static enum Type { + HASH, + ISO, // three letter isoCode + DEMURRAGE, + UNKNOWN; + + public static Type fromByte(byte typeByte) { + if (typeByte == 0x00) { + return ISO; + } else if (typeByte == 0x01) { + return DEMURRAGE; + } else if ((typeByte & 0x80) != 0) { + return HASH; + } else { + return UNKNOWN; + } + } + } + Type type; + + public static class Demurrage { + Date interestStart; + String isoCode; + double interestRate; + + static public BigDecimal applyRate(BigDecimal amount, BigDecimal rate, TimeUnit time, long units) { + BigDecimal appliedRate = getSeconds(time, units).divide(rate, MathContext.DECIMAL64); + BigDecimal factor = BigDecimal.valueOf(Math.exp(appliedRate.doubleValue())); + return amount.multiply(factor, MathContext.DECIMAL64); + } + + static public BigDecimal calculateRate(BigDecimal rate, TimeUnit time, long units) { + BigDecimal seconds = getSeconds(time, units); + BigDecimal log = ln(rate); + return seconds.divide(log, MathContext.DECIMAL64); + } + + private static BigDecimal ln(BigDecimal bd) { + return BigDecimal.valueOf(Math.log(bd.doubleValue())); + } + + private static BigDecimal getSeconds(TimeUnit time, long units) { + return BigDecimal.valueOf(time.toSeconds(units)); + } + + public Demurrage(byte[] bytes) { + BinaryParser parser = new BinaryParser(bytes); + parser.skip(1); // The type + isoCode = isoCodeFromBytesAndOffset(parser.read(3), 0);// The isoCode + interestStart = RippleDate.fromParser(parser); + long l = UInt64.fromParser(parser).longValue(); + interestRate = Double.longBitsToDouble(l); + } + } + public Demurrage demurrage = null; + public Currency(byte[] bytes) { + super(bytes); + type = Type.fromByte(this.hash[0]); + if (type == Type.DEMURRAGE) { + demurrage = new Demurrage(bytes); + } + } + + /** + * It's better to extend HashTranslator than the Hash160.Translator directly + * That way the generics can still vibe with the @Override + */ + private static class CurrencyTranslator extends HashTranslator { + @Override + public int byteWidth() { + return 20; + } + + @Override + public Currency newInstance(byte[] b) { + return new Currency(b); + } + + @Override + public Object toJSON(Currency obj) { + return obj.toString(); + } + + @Override + public Currency fromString(String value) { + if (value.length() == 40 /* byteWidth() * 2 */) { + return newInstance(B16.decode(value)); + } else if (value.equals("XRP")) { + return XRP; + } else { + if (!(value.length() == 3)) { +// if (!value.matches("[A-Z0-9]{3}")) { + throw new RuntimeException("Currency code must be 3 characters"); + } + return newInstance(encodeCurrency(value)); + } + } + } + + public static Currency fromString(String currency) { + return translate.fromString(currency); + } + + public static Currency fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + @Override + public String toString() { + switch (type) { + case ISO: + String code = getCurrencyCodeFromTLCBytes(bytes()); + if (code.equals("XRP")) { + // HEX of the bytes + return super.toString(); + } else if (code.equals("\0\0\0")) { + return "XRP"; + } else { + // the 3 letter isoCode + return code; + } + case HASH: + case DEMURRAGE: + case UNKNOWN: + default: + return super.toString(); + } + } + + public String humanCode() { + if (type == Type.ISO) { + return getCurrencyCodeFromTLCBytes(hash); + } else if (type == Type.DEMURRAGE) { + return isoCodeFromBytesAndOffset(hash, 1); + } else { + throw new IllegalStateException("No human code for currency of type " + type); + } + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Currency) { + Currency other = (Currency) obj; + byte[] bytes = this.bytes(); + byte[] otherBytes = other.bytes(); + + if (type == Type.ISO && other.type == Type.ISO) { + return (bytes[12] == otherBytes[12] && + bytes[13] == otherBytes[13] && + bytes[14] == otherBytes[14]); + } + } + return super.equals(obj); // Full comparison + } + + private static CurrencyTranslator translate = new CurrencyTranslator(); + + /* + * The following are static methods, legacy from when there was no + * usage of Currency objects, just String with "XRP" ambiguity. + * */ + public static byte[] encodeCurrency(String currencyCode) { + byte[] currencyBytes = new byte[20]; + currencyBytes[12] = (byte) currencyCode.codePointAt(0); + currencyBytes[13] = (byte) currencyCode.codePointAt(1); + currencyBytes[14] = (byte) currencyCode.codePointAt(2); + return currencyBytes; + } + + public static String getCurrencyCodeFromTLCBytes(byte[] bytes) { + int i; + boolean zeroInNonCurrencyBytes = true; + + for (i = 0; i < 20; i++) { + zeroInNonCurrencyBytes = zeroInNonCurrencyBytes && + ((i == 12 || i == 13 || i == 14) || // currency bytes (0 or any other) + bytes[i] == 0); // non currency bytes (0) + } + + if (zeroInNonCurrencyBytes) { + return isoCodeFromBytesAndOffset(bytes, 12); + } else { + throw new IllegalStateException("Currency is invalid"); + } + } + + private static char charFrom(byte[] bytes, int i) { + return (char) bytes[i]; + } + + private static String isoCodeFromBytesAndOffset(byte[] bytes, int offset) { + char a = charFrom(bytes, offset); + char b = charFrom(bytes, offset + 1); + char c = charFrom(bytes, offset + 2); + return "" + a + b + c; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java new file mode 100644 index 0000000000..9b0c319dcf --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java @@ -0,0 +1,35 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; + +import java.util.BitSet; + +// TODO +public class Flags extends BitSet implements SerializedType { + @Override + public Object toJSON() { + return null; + } + + @Override + public byte[] toBytes() { + return new byte[0]; + } + + @Override + public String toHex() { + return null; + } + + @Override + public void toBytesSink(BytesSink to) { + + } + + @Override + public Type type() { + return Type.UInt32; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java new file mode 100644 index 0000000000..44f75dae82 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java @@ -0,0 +1,101 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.coretypes.hash.Hash160; +import org.json.JSONObject; + +import java.math.BigDecimal; + +/** + * Represents a currency/issuer pair + */ +public class Issue implements Comparable { + + public static final Issue XRP = fromString("XRP"); + final Currency currency; + final AccountID issuer; + + public Issue(Currency currency, AccountID issuer) { + this.currency = currency; + this.issuer = issuer; + } + + public static Issue fromString(String pair) { + String[] split = pair.split("/"); + return fromStringPair(split); + } + + private static Issue fromStringPair(String[] split) { + if (split.length == 2) { + return new Issue(Currency.fromString(split[0]), AccountID.fromString(split[1])); + } else if (split[0].equals("XRP")) { + return new Issue(Currency.XRP, AccountID.XRP_ISSUER); + } else { + throw new RuntimeException("Issue string must be XRP or $currency/$issuer"); + } + } + + /** + * See {@link com.ripple.core.fields.Field#TakerGetsCurrency} + * See {@link com.ripple.core.fields.Field#TakerGetsIssuer} + * + * TODO: better handling of Taker(Gets|Pays)(Issuer|Curency) + * maybe special subclasses of AccountID / Currency + * respectively? + */ + public static Issue from160s(Hash160 currency, Hash160 issuer) { + return new Issue(new Currency(currency.bytes()), + new AccountID(issuer.toBytes())); + } + + public Currency currency() { + return currency; + } + + public AccountID issuer() { + return issuer; + } + + @Override + public String toString() { + if (isNative()) { + return "XRP"; + } else { + return String.format("%s/%s", currency, issuer); + } + } + + public JSONObject toJSON() { + JSONObject o = new JSONObject(); + o.put("currency", currency); + if (!isNative()) { + o.put("issuer", issuer); + } + return o; + } + + public Amount amount(BigDecimal value) { + return new Amount(value, currency, issuer, isNative()); + } + + public boolean isNative() { + return this == XRP || currency.equals(Currency.XRP); + } + + public Amount amount(Number value) { + return new Amount(BigDecimal.valueOf(value.doubleValue()), currency, issuer, isNative()); + } + + @Override + public int compareTo(Issue o) { + int ret = issuer.compareTo(o.issuer); + if (ret != 0) { + return ret; + } + ret = currency.compareTo(o.currency); + return ret; + } + + public Amount roundedAmount(BigDecimal amount) { + return amount(Amount.roundValue(amount, isNative())); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java b/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java new file mode 100644 index 0000000000..0196e67f86 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java @@ -0,0 +1,36 @@ +package com.ripple.core.coretypes; + +import org.json.JSONObject; + +import java.text.MessageFormat; + +public class IssuePair implements Comparable { + public final Issue pays; + public final Issue gets; + + public IssuePair(Issue pays, Issue gets) { + this.pays = pays; + this.gets = gets; + } + + @Override + public String toString() { + return MessageFormat.format("{0}/{1}", pays, gets); + } + + @Override + public int compareTo(IssuePair o) { + int cmp = pays.compareTo(o.pays); + if (cmp == 0) { + cmp = gets.compareTo(o.gets); + } + return cmp; + } + + public JSONObject toJSON() { + JSONObject ret = new JSONObject(); + ret.put("taker_gets", gets.toJSON()); + ret.put("taker_pays", pays.toJSON()); + return ret; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java b/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java new file mode 100644 index 0000000000..b054229787 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java @@ -0,0 +1,273 @@ +package com.ripple.core.coretypes; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.PathSetField; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; + +public class PathSet extends ArrayList implements SerializedType { + public static byte PATH_SEPARATOR_BYTE = (byte) 0xFF; + public static byte PATHSET_END_BYTE = (byte) 0x00; + + public PathSet(){} + + public static PathSet fromJSONArray(JSONArray array) { + return translate.fromJSONArray(array); + } + + public static PathSet fromHex(String hex) { + return translate.fromHex(hex); + } + + public static class Hop { + public static byte TYPE_ACCOUNT = (byte) 0x01; + public static byte TYPE_CURRENCY = (byte) 0x10; + public static byte TYPE_ISSUER = (byte) 0x20; + public static final int TYPE_ACCOUNT_CURRENCY_ISSUER = TYPE_CURRENCY | TYPE_ACCOUNT | TYPE_ISSUER; + public static final int TYPE_ACCOUNT_CURRENCY = TYPE_CURRENCY | TYPE_ACCOUNT; + public static int VALID_TYPE_MASK = ~(TYPE_ACCOUNT | TYPE_CURRENCY | TYPE_ISSUER); + + public AccountID account; + public AccountID issuer; + public Currency currency; + private int type; + + public boolean hasIssuer() { + return issuer != null; + } + public boolean hasCurrency() { + return currency != null; + } + public boolean hasAccount() { + return account != null; + } + + public int getType() { + if (type == 0) { + synthesizeType(); + } + return type; + } + + static public Hop fromJSONObject(JSONObject json) { + Hop hop = new Hop(); + if (json.has("account")) { + hop.account = AccountID.fromAddress(json.getString("account")); + } + if (json.has("issuer")) { + hop.issuer = AccountID.fromAddress(json.getString("issuer")); + } + if (json.has("currency")) { + hop.currency = Currency.fromString(json.getString("currency")); + } + if (json.has("type")) { + hop.type = json.getInt("type"); + } + return hop; + } + + public void synthesizeType() { + type = 0; + + if (hasAccount()) type |= TYPE_ACCOUNT; + if (hasCurrency()) type |= TYPE_CURRENCY; + if (hasIssuer()) type |= TYPE_ISSUER; + } + + public JSONObject toJSONObject() { + JSONObject object = new JSONObject(); + object.put("type", getType()); + + if (hasAccount()) object.put("account", account.toJSON()); + if (hasIssuer()) object.put("issuer", issuer.toJSON()); + if (hasCurrency()) object.put("currency", currency.toJSON()); + return object; + } + + public static Hop fromJacksonObject(ObjectNode json) { + Hop hop = new Hop(); + if (json.has("account")) { + hop.account = AccountID.fromAddress(json.get("account").asText()); + } + if (json.has("issuer")) { + hop.issuer = AccountID.fromAddress(json.get("issuer").asText()); + } + if (json.has("currency")) { + hop.currency = Currency.fromString(json.get("currency").asText()); + } + if (json.has("type")) { + hop.type = json.get("type").asInt(); + } + return hop; + + } + } + public static class Path extends ArrayList { + static public Path fromJSONArray(JSONArray array) { + Path path = new Path(); + int nHops = array.length(); + for (int i = 0; i < nHops; i++) { + JSONObject hop = array.getJSONObject(i); + path.add(Hop.fromJSONObject(hop)); + } + + return path; + } + static public Path fromJacksonArray(ArrayNode array) { + Path path = new Path(); + int nHops = array.size(); + for (int i = 0; i < nHops; i++) { + ObjectNode hop = (ObjectNode) array.get(i); + path.add(Hop.fromJacksonObject(hop)); + } + return path; + } + public JSONArray toJSONArray() { + JSONArray array = new JSONArray(); + for (Hop hop : this) { + array.put(hop.toJSONObject()); + } + return array; + } + } + + public JSONArray toJSONArray() { + JSONArray array = new JSONArray(); + for (Path path : this) { + array.put(path.toJSONArray()); + } + return array; + } + + // SerializedType interface implementation + @Override + public Object toJSON() { + return toJSONArray(); + } + + @Override + public void toBytesSink(BytesSink buffer) { + int n = 0; + for (Path path : this) { + if (n++ != 0) { + buffer.add(PATH_SEPARATOR_BYTE); + } + for (Hop hop : path) { + int type = hop.getType(); + buffer.add((byte) type); + if (hop.hasAccount()) { + buffer.add(hop.account.bytes()); + } + if (hop.hasCurrency()) { + buffer.add(hop.currency.bytes()); + } + if (hop.hasIssuer()) { + buffer.add(hop.issuer.bytes()); + } + } + } + buffer.add(PATHSET_END_BYTE); + } + + @Override + public Type type() { + return Type.PathSet; + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + + public static class Translator extends TypeTranslator { + @Override + public PathSet fromParser(BinaryParser parser, Integer hint) { + PathSet pathSet = new PathSet(); + PathSet.Path path = null; + while (!parser.end()) { + byte type = parser.readOne(); + if (type == PATHSET_END_BYTE) { + break; + } + if (path == null) { + path = new PathSet.Path(); + pathSet.add(path); + } + if (type == PATH_SEPARATOR_BYTE) { + path = null; + continue; + } + + PathSet.Hop hop = new PathSet.Hop(); + path.add(hop); + if ((type & Hop.TYPE_ACCOUNT) != 0) { + hop.account = AccountID.fromParser(parser); + } + if ((type & Hop.TYPE_CURRENCY) != 0) { + hop.currency = Currency.fromParser(parser); + } + if ((type & Hop.TYPE_ISSUER) != 0) { + hop.issuer = AccountID.fromParser(parser); + } + } + + return pathSet; + } + + @Override + public PathSet fromJSONArray(JSONArray array) { + PathSet paths = new PathSet(); + + int nPaths = array.length(); + + for (int i = 0; i < nPaths; i++) { + JSONArray path = array.getJSONArray(i); + paths.add(Path.fromJSONArray(path)); + } + return paths; + + } + + @Override + public PathSet fromJacksonArray(ArrayNode array) { + PathSet paths = new PathSet(); + + int nPaths = array.size(); + + for (int i = 0; i < nPaths; i++) { + ArrayNode path = (ArrayNode) array.get(i); + paths.add(Path.fromJacksonArray(path)); + } + + return paths; + } + } + static public Translator translate = new Translator(); + + public static PathSet fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + public static PathSet fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + private static PathSetField pathsetField(final Field f) { + return new PathSetField(){ @Override public Field getField() {return f;}}; + } + static public PathSetField Paths = pathsetField(Field.Paths); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java new file mode 100644 index 0000000000..212da6d78e --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java @@ -0,0 +1,26 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.coretypes.hash.Hash256; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class Quality { + /** + * Finds the quality (TakerPays/TakerGets) ratio packed into the last 64 + * bits of root DirectoryNode ledger indexes. + */ + public static BigDecimal fromBookDirectory(Hash256 bookDirectory, + boolean payIsNative, + boolean getIsNative) { + // The last 7 bytes contains the mantissa + byte[] mantissa = bookDirectory.slice(-7); + // Most significant byte has the exponent packed + int exponent = ( bookDirectory.get(-8) & 0xFF) - 100; + // Return the value in XRP scale, rather than drops, as stored. + int scale = -(payIsNative ? exponent - 6 : + getIsNative ? exponent + 6 : exponent); + BigInteger unsignedBig = new BigInteger(1, mantissa); + return new BigDecimal(unsignedBig, scale); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java b/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java new file mode 100644 index 0000000000..71a94e1ce9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java @@ -0,0 +1,82 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.BinaryParser; + +import java.text.SimpleDateFormat; +import java.util.*; + +//public class RippleDate extends Date implements SerializedType { +public class RippleDate extends Date { + private static final SimpleDateFormat sdf = new SimpleDateFormat(); + + public static long RIPPLE_EPOCH_SECONDS_OFFSET = 0x386D4380; + static { + sdf.setTimeZone(new SimpleTimeZone(0, "GMT")); + sdf.applyPattern("dd MMM yyyy HH:mm:ss z"); + + /** + * Magic constant tested and documented. + * + * Seconds since the unix epoch from unix time (accounting leap years etc) + * at 1/January/2000 GMT + */ + GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + cal.set(2000, Calendar.JANUARY, 1, 0, 0, 0); + long computed = cal.getTimeInMillis() / 1000; + assertEquals("01 Jan 2000 00:00:00 GMT", sdf.format(cal.getTime())); // TODO + assertEquals(RippleDate.RIPPLE_EPOCH_SECONDS_OFFSET, computed); + } + + static public String gmtString(Date date) { + return sdf.format(date); + } + + private static void assertEquals(String s, String s1) { + if (!s.equals(s1)) throw new AssertionError(String.format("%s != %s", s, s1)); + } + private static void assertEquals(long a, long b) { + if (a != b) throw new AssertionError(String.format("%s != %s", a, b)); + } + + private RippleDate() { + super(); + } + private RippleDate(long milliseconds) { + super(milliseconds); + } + + public long secondsSinceRippleEpoch() { + return ((this.getTime() / 1000) - RIPPLE_EPOCH_SECONDS_OFFSET); + } + public static RippleDate fromSecondsSinceRippleEpoch(Number seconds) { + return new RippleDate((seconds.longValue() + RIPPLE_EPOCH_SECONDS_OFFSET) * 1000); + } + public static RippleDate fromParser(BinaryParser parser) { + UInt32 uInt32 = UInt32.fromParser(parser); + return fromSecondsSinceRippleEpoch(uInt32); + } + public static RippleDate now() { + return new RippleDate(); + } + +/* @Override + public Object toJSON() { + return secondsSinceRippleEpoch(); + } + + @Override + public byte[] toBytes() { + return new UInt32(secondsSinceRippleEpoch()).toBytes(); + } + + @Override + public String toHex() { + return new UInt32(secondsSinceRippleEpoch()).toHex(); + } + + @Override + public void toBytesSink(BytesSink to) { + new UInt32(secondsSinceRippleEpoch()).toBytesSink(to); + }*/ +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java new file mode 100644 index 0000000000..6e7b0191f3 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java @@ -0,0 +1,129 @@ +package com.ripple.core.coretypes; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.STArrayField; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; + +public class STArray extends ArrayList implements SerializedType { + + public JSONArray toJSONArray() { + JSONArray array = new JSONArray(); + + for (STObject so : this) { + array.put(so.toJSON()); + } + + return array; + } + + @Override + public Object toJSON() { + return toJSONArray(); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + for (STObject stObject : this) { + stObject.toBytesSink(to); + } + } + + @Override + public Type type() { + return Type.STArray; + } + + public static STArray fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + public static STArray fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + public static STArray fromHex(String hex) { + return translate.fromHex(hex); + } + + public static class Translator extends TypeTranslator { + @Override + public STArray fromParser(BinaryParser parser, Integer hint) { + STArray stArray = new STArray(); + while (!parser.end()) { + Field field = parser.readField(); + if (field == Field.ArrayEndMarker) { + break; + } + STObject outer = new STObject(); + // assert field.getType() == Type.STObject; + outer.put(field, STObject.fromParser(parser)); + stArray.add(STObject.formatted(outer)); + } + return stArray; + } + + public JSONArray toJSONArray(STArray obj) { + return obj.toJSONArray(); + } + + @Override + public STArray fromJSONArray(JSONArray jsonArray) { + STArray arr = new STArray(); + + for (int i = 0; i < jsonArray.length(); i++) { + Object o = jsonArray.get(i); + arr.add(STObject.fromJSONObject((JSONObject) o)); + } + + return arr; + } + @Override + public STArray fromJacksonArray(ArrayNode jsonArray) { + STArray arr = new STArray(); + + for (int i = 0; i < jsonArray.size(); i++) { + ObjectNode object = (ObjectNode) jsonArray.get(i); + arr.add(STObject.fromJacksonObject(object)); + } + + return arr; + } + } + static public Translator translate = new Translator(); + + public STArray(){} + + private static STArrayField starrayField(final Field f) { + return new STArrayField(){ @Override public Field getField() {return f;}}; + } + + static public STArrayField AffectedNodes = starrayField(Field.AffectedNodes); + static public STArrayField SignerEntries = starrayField(Field.SignerEntries); + static public STArrayField Signers = starrayField(Field.Signers); + + static public STArrayField Template = starrayField(Field.Template); + static public STArrayField Necessary = starrayField(Field.Necessary); + static public STArrayField Sufficient = starrayField(Field.Sufficient); + static public STArrayField Majorities = starrayField(Field.Majorities); + static public STArrayField Memos = starrayField(Field.Memos); + static public STArrayField ArrayEndMarker = starrayField(Field.ArrayEndMarker); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java new file mode 100644 index 0000000000..b02988c082 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java @@ -0,0 +1,489 @@ +package com.ripple.core.coretypes; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash128; +import com.ripple.core.coretypes.hash.Hash160; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.uint.UInt16; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.fields.*; +import com.ripple.core.formats.Format; +import com.ripple.core.formats.LEFormat; +import com.ripple.core.formats.TxFormat; +import com.ripple.core.serialized.*; +import com.ripple.core.serialized.enums.EngineResult; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.serialized.enums.TransactionType; +import org.json.JSONObject; + +import java.util.EnumMap; +import java.util.Iterator; +import java.util.TreeMap; +import java.util.function.Predicate; + +public class STObject implements SerializedType, Iterable { + // Internally the fields are stored in a TreeMap + public static class FieldsMap extends TreeMap {} +// public static class FieldsMap extends HashMap {} + + protected FieldsMap fields; + public Format format; + + public STObject() { + fields = new FieldsMap(); + } + public STObject(FieldsMap fieldsMap) { + fields = fieldsMap; + } + + public static STObject fromJSON(String json) { + return fromJSONObject(new JSONObject(json)); + } + public static STObject fromJSONObject(JSONObject json) { + return translate.fromJSONObject(json); + } + public static STObject fromJacksonObject(ObjectNode object) { + return translate.fromJacksonObject(object); + } + public static STObject fromHex(String hex) { + return STObject.translate.fromHex(hex); + } + public static STObject fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + public static STObject fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + public static STObject fromParser(BinaryParser parser, Integer hint) { + return translate.fromParser(parser, hint); + } + + @Override + public Iterator iterator() { +// return fields.keySet().stream().sorted().iterator(); + return fields.keySet().iterator(); + } + + public String prettyJSON() { + return translate.toJSONObject(this).toString(2); + } + + /** + * @return a subclass of STObject using the same fields + * + * If the object has a TransactionType or LedgerEntryType + * then we can up)grade to a child class, with more specific + * helper methods, and we can use `instanceof` to great effect. + */ + public static STObject formatted(STObject source) { + return STObjectFormatter.format(source); + + } + + public Format getFormat() { + if (format == null) computeFormat(); + return format; + } + + public static class FormatException extends RuntimeException { + FormatException(String s) { + super(s); + } + } + + public void checkFormat() { + Format fmt = getFormat(); + EnumMap requirements = fmt.requirements(); + for (Field field : this) { + if (!requirements.containsKey(field)) { + throw new FormatException(fmt.name() + + " doesn't have field: " + field); + } + } + for (Field field : requirements.keySet()) { + Format.Requirement req = requirements.get(field); + if (!has(field)) { + if (req == Format.Requirement.REQUIRED) { + throw new FormatException(fmt.name() + + " requires " + field + " of type " + + field.getType()); + } + } else { + SerializedType type = get(field); + if (type.type() != field.getType()) { + if (!(field.getType() == Type.Hash160 && + type.type() == Type.AccountID)) { + throw new FormatException(type.toString() + + " is not " + field.getType()); + } + } + } + } + } + + public void setFormat(Format format) { + this.format = format; + } + + private void computeFormat() { + UInt16 tt = get(UInt16.TransactionType); + if (tt != null) { + setFormat(TxFormat.fromNumber(tt)); + } + UInt16 let = get(UInt16.LedgerEntryType); + if (let != null) { + setFormat(LEFormat.fromNumber(let)); + } + } + + public FieldsMap getFields() { + return fields; + } + + public SerializedType get(Field field) { + return fields.get(field); + } + + protected Hash256 signingHash(HashPrefix txSign) { + HalfSha512 signing = HalfSha512.prefixed256(txSign); + toBytesSink(signing, Field::isSigningField); + return signing.finish(); + } + + protected byte[] signingData(HashPrefix txSign) { + BytesList bl = new BytesList(); + bl.add(txSign.bytes()); + toBytesSink(bl, Field::isSigningField); + return bl.bytes(); + } + + protected static EngineResult engineResult(STObject obj) { + return (EngineResult) obj.get(Field.TransactionResult); + } + + static public LedgerEntryType ledgerEntryType(STObject obj) { + return (LedgerEntryType) obj.get(Field.LedgerEntryType); + } + + public static TransactionType transactionType(STObject obj) { + return (TransactionType) obj.get(Field.TransactionType); + } + + public SerializedType remove(Field f) { + return fields.remove(f); + } + + public boolean has(Field f) { + return fields.containsKey(f); + } + + public boolean has(T hf) { + return has(hf.getField()); + } + + public void put (UInt8Field f, UInt8 o) {put(f.getField(), o);} + public void put (Vector256Field f, Vector256 o) {put(f.getField(), o);} + public void put (BlobField f, Blob o) {put(f.getField(), o);} + public void put (UInt64Field f, UInt64 o) {put(f.getField(), o);} + public void put (UInt32Field f, UInt32 o) {put(f.getField(), o);} + public void put (UInt16Field f, UInt16 o) {put(f.getField(), o);} + public void put (PathSetField f, PathSet o) {put(f.getField(), o);} + public void put (STObjectField f, STObject o) {put(f.getField(), o);} + public void put (Hash256Field f, Hash256 o) {put(f.getField(), o);} + public void put (Hash160Field f, Hash160 o) {put(f.getField(), o);} + public void put (Hash128Field f, Hash128 o) {put(f.getField(), o);} + public void put (STArrayField f, STArray o) {put(f.getField(), o);} + public void put (AmountField f, Amount o) {put(f.getField(), o);} + public void put (AccountIDField f, AccountID o) {put(f.getField(), o);} + + public void putTranslated(T f, Object value) { + putTranslated(f.getField(), value); + } + + public STObject as(T f, Object value) { + putTranslated(f.getField(), value); + return this; + } + + public void put(Field f, SerializedType value) { + fields.put(f, value); + } + + public void putTranslated(Field f, Object value) { + TypeTranslator typeTranslator = Translators.forField(f); + SerializedType st; + try { + st = typeTranslator.fromValue(value); + } catch (Exception e) { + throw new RuntimeException("Couldn't put `" +value+ "` into field `" + f + "`", e); + } + fields.put(f, st); + } + + public AccountID get(AccountIDField f) { + return (AccountID) get(f.getField()); + } + + public Amount get(AmountField f) { + return (Amount) get(f.getField()); + } + + public STArray get(STArrayField f) { + return (STArray) get(f.getField()); + } + + public Hash128 get(Hash128Field f) { + return (Hash128) get(f.getField()); + } + + public Hash160 get(Hash160Field f) { + return (Hash160) get(f.getField()); + } + + public Hash256 get(Hash256Field f) { + return (Hash256) get(f.getField()); + } + + public STObject get(STObjectField f) { + return (STObject) get(f.getField()); + } + + public PathSet get(PathSetField f) { + return (PathSet) get(f.getField()); + } + + public UInt16 get(UInt16Field f) { + return (UInt16) get(f.getField()); + } + + public UInt32 get(UInt32Field f) { + return (UInt32) get(f.getField()); + } + + public UInt64 get(UInt64Field f) { + return (UInt64) get(f.getField()); + } + + public UInt8 get(UInt8Field f) { + return (UInt8) get(f.getField()); + } + + public Vector256 get(Vector256Field f) { + return (Vector256) get(f.getField()); + } + + public Blob get(BlobField f) { + return (Blob) get(f.getField()); + } + + // SerializedTypes implementation + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + public JSONObject toJSONObject() { + return translate.toJSONObject(this); + } + + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + public void toBytesSink(BytesSink to, Predicate p) { + BinarySerializer serializer = new BinarySerializer(to); + + for (Field field : this) { + if (p.test(field)) { + SerializedType value = fields.get(field); + serializer.add(field, value); + } + } + } + @Override + public void toBytesSink(BytesSink to) { + toBytesSink(to, field -> field.isSerialized()); + } + + @Override + public Type type() { + return Type.STObject; + } + + private static class Translator extends TypeTranslator { + + @Override + public STObject fromParser(BinaryParser parser, Integer hint) { + STObject so = new STObject(); + TypeTranslator tr; + SerializedType st; + Field field; + Integer sizeHint; + + // hint, is how many bytes to parse + if (hint != null) { + // end hint + hint = parser.pos() + hint; + } + + while (!parser.end(hint)) { + field = parser.readField(); + if (field == Field.ObjectEndMarker) { + break; + } + tr = Translators.forField(field); + sizeHint = field.isVLEncoded() ? parser.readVLLength() : null; + st = tr.fromParser(parser, sizeHint); + if (st == null) { + throw new IllegalStateException("Parsed " + field + " as null"); + } + so.put(field, st); + } + + return STObject.formatted(so); + } + + @Override + public Object toJSON(STObject obj) { + return toJSONObject(obj); + } + + public JSONObject toJSONObject(STObject obj) { + JSONObject json = new JSONObject(); + + for (Field f : obj) { + SerializedType obj1 = obj.get(f); + Object object = obj1.toJSON(); + json.put(f.name(), object); + } + + return json; + } + + @Override + public STObject fromJSONObject(JSONObject jsonObject) { + STObject so = new STObject(); + + Iterator keys = jsonObject.keys(); + while (keys.hasNext()) { + String key = (String) keys.next(); + Object value = jsonObject.get(key); + Field fieldKey = Field.fromString(key); + if (fieldKey == null) { + continue; + } + so.putTranslated(fieldKey, value); + } + return STObject.formatted(so); + } + + @Override + public STObject fromJacksonObject(ObjectNode object) { + STObject so = new STObject(); + + Iterator keys = object.fieldNames(); + while (keys.hasNext()) { + String key = keys.next(); + JsonNode value = object.get(key); + Field fieldKey = Field.fromString(key); + if (fieldKey == null) { + continue; + } + so.putTranslated(fieldKey, value); + } + return STObject.formatted(so); + } + } + + public int size() { + return fields.size(); + } + + static private Translator translate = new Translator(); + + private static STObjectField stobjectField(final Field f) { + return new STObjectField() {@Override public Field getField() {return f; } }; + } + + static public STObjectField TransactionMetaData = stobjectField(Field.TransactionMetaData); + static public STObjectField CreatedNode = stobjectField(Field.CreatedNode); + static public STObjectField DeletedNode = stobjectField(Field.DeletedNode); + static public STObjectField ModifiedNode = stobjectField(Field.ModifiedNode); + static public STObjectField PreviousFields = stobjectField(Field.PreviousFields); + static public STObjectField FinalFields = stobjectField(Field.FinalFields); + static public STObjectField NewFields = stobjectField(Field.NewFields); + static public STObjectField TemplateEntry = stobjectField(Field.TemplateEntry); + static public STObjectField Signer = stobjectField(Field.Signer); + static public STObjectField SignerEntry = stobjectField(Field.SignerEntry); + static public STObjectField ObjectEndMarker = stobjectField(Field.ObjectEndMarker); + static public STObjectField Memo = stobjectField(Field.Memo); + static public STObjectField Majority = stobjectField(Field.Majority); + + private static class Translators { + @SuppressWarnings("unused") + private static TypeTranslator get(Class kls) { + try { + java.lang.reflect.Field translate = kls.getDeclaredField("translate"); + translate.setAccessible(true); + return (TypeTranslator) translate.get(kls); + } catch (Exception e) { + throw new RuntimeException("for kls: " + kls.getSimpleName(), e); + } + } + + private static TypeTranslator forType(Type type) { + switch (type) { + case STObject: return STObject.translate; // get(STObject.class); + case Amount: return Amount.translate; // get(Amount.class); + case UInt16: return UInt16.translate; // get(UInt16.class); + case UInt32: return UInt32.translate; // get(UInt32.class); + case UInt64: return UInt64.translate; // get(UInt64.class); + case Hash128: return Hash128.translate; // get(Hash128.class); + case Hash256: return Hash256.translate; // get(Hash256.class); + case Blob: return Blob.translate; // get(Blob.class); + case AccountID: return AccountID.translate; // get(AccountID.class); + case STArray: return STArray.translate; // get(STArray.class); + case UInt8: return UInt8.translate; // get(UInt8.class); + case Hash160: return Hash160.translate; // get(Hash160.class); + case PathSet: return PathSet.translate; // get(PathSet.class); + case Vector256: return Vector256.translate; // get(Vector256.class); + default: throw new IllegalStateException("Unknown type"); + } + } + + private static TypeTranslator forField(Field field) { + if (field.tag == null) { + switch (field) { + case LedgerEntryType: + field.tag = LedgerEntryType.translate; //get(LedgerEntryType.class); + break; + case TransactionType: + field.tag = TransactionType.translate;// get(TransactionType.class); + break; + case TransactionResult: + field.tag = EngineResult.translate; // get(EngineResult.class); + break; + default: + field.tag = forType(field.getType()); + break; + } + } + return getCastedTag(field); + } + + @SuppressWarnings("unchecked") + private static TypeTranslator getCastedTag(Field field) { + return (TypeTranslator) field.tag; + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java new file mode 100644 index 0000000000..d17b6ae0ee --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java @@ -0,0 +1,170 @@ +package com.ripple.core.coretypes; + +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.generic.Validation; +import com.ripple.core.types.known.sle.LedgerHashes; +import com.ripple.core.types.known.sle.entries.*; +import com.ripple.core.types.known.tx.result.AffectedNode; +import com.ripple.core.types.known.tx.result.TransactionMeta; +import com.ripple.core.types.known.tx.txns.*; +import com.ripple.core.types.known.tx.txns.pseudo.EnableAmendment; +import com.ripple.core.types.known.tx.txns.pseudo.SetFee; + +public class STObjectFormatter { + public static STObject format(STObject source) { + // This would need to go before the test that just checks + // for ledgerEntryType + if (AffectedNode.isAffectedNode(source)) { + return new AffectedNode(source); + } + + if (TransactionMeta.isTransactionMeta(source)) { + TransactionMeta meta = new TransactionMeta(); + meta.fields = source.fields; + return meta; + } + + LedgerEntryType ledgerEntryType = STObject.ledgerEntryType(source); + if (ledgerEntryType != null) { + return ledgerFormatted(source, ledgerEntryType); + } + + TransactionType transactionType = STObject.transactionType(source); + if (transactionType != null) { + return transactionFormatted(source, transactionType); + } + + if (Validation.isValidation(source)) { + Validation validation = new Validation(); + validation.fields = source.fields; + return validation; + } + + return source; + } + + private static STObject transactionFormatted(STObject source, TransactionType transactionType) { + STObject constructed = null; + switch (transactionType) { + case Payment: + constructed = new Payment(); + break; + case EscrowCreate: + constructed = new EscrowCreate(); + break; + case EscrowFinish: + constructed = new EscrowFinish(); + break; + case AccountSet: + constructed = new AccountSet(); + break; + case EscrowCancel: + constructed = new EscrowCancel(); + break; + case SetRegularKey: + constructed = new SetRegularKey(); + break; + case OfferCreate: + constructed = new OfferCreate(); + break; + case OfferCancel: + constructed = new OfferCancel(); + break; + case TicketCreate: + constructed = new TicketCreate(); + break; + case TicketCancel: + constructed = new TicketCancel(); + break; + case SignerListSet: + constructed = new SignerListSet(); + break; + case PaymentChannelCreate: + constructed = new PaymentChannelCreate(); + break; + case PaymentChannelFund: + constructed = new PaymentChannelFund(); + break; + case PaymentChannelClaim: + constructed = new PaymentChannelClaim(); + break; + case CheckCreate: + constructed = new CheckCreate(); + break; + case CheckCash: + constructed = new CheckCash(); + break; + case CheckCancel: + constructed = new CheckCancel(); + break; + case DepositPreauth: + constructed = new DepositPreauth(); + break; + case TrustSet: + constructed = new TrustSet(); + break; + case EnableAmendment: + constructed = new EnableAmendment(); + break; + case SetFee: + constructed = new SetFee(); + break; + } + + constructed.fields = source.fields; + return constructed; + + } + + private static STObject ledgerFormatted(STObject source, LedgerEntryType ledgerEntryType) { + STObject constructed = null; + switch (ledgerEntryType) { + case Escrow: + constructed = new Escrow(); + break; + case Offer: + constructed = new Offer(); + break; + case RippleState: + constructed = new RippleState(); + break; + case AccountRoot: + constructed = new AccountRoot(); + break; + case DirectoryNode: + if (source.has(AccountID.Owner)) { + constructed = new OwnerDirectory(); + } else { + constructed = new OfferDirectory(); + } + break; + case LedgerHashes: + constructed = new LedgerHashes(); + break; + case Amendments: + constructed = new Amendments(); + break; + case FeeSettings: + constructed = new FeeSettings(); + break; + case Ticket: + constructed = new Ticket(); + break; + case SignerList: + constructed = new SignerList(); + break; + case PayChannel: + constructed = new PayChannel(); + break; + case Check: + constructed = new Check(); + break; + case DepositPreauth: + constructed = new DepositPreauthLe(); + break; + } + constructed.fields = source.fields; + return constructed; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java new file mode 100644 index 0000000000..8a5eef49e5 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java @@ -0,0 +1,141 @@ +package com.ripple.core.coretypes; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.fields.Vector256Field; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; +import org.json.JSONArray; + +import java.util.ArrayList; + +public class Vector256 extends ArrayList implements SerializedType { + + @Override + public Object toJSON() { + return toJSONArray(); + } + + public JSONArray toJSONArray() { + JSONArray array = new JSONArray(); + + for (Hash256 hash256 : this) { + array.put(hash256.toString()); + } + + return array; + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + for (Hash256 hash256 : this) { + hash256.toBytesSink(to); + } + } + + @Override + public Type type() { + return Type.Vector256; + } + + /** + * This method puts the last element in the removed elements slot, and + * pops off the back, thus preserving contiguity but losing ordering. + * @param ledgerIndex the ledger entry index to remove + * + * Unused when the featureSortedDirectories amendment is applied: + * See: https://ripple.com/build/known-amendments/#sorteddirectories + */ + public boolean removeUnstable(Hash256 ledgerIndex) { + int i = indexOf(ledgerIndex); + if (i == -1) { + return false; + } + + int last = size() - 1; + Hash256 lastIndex = get(last); + set(i, lastIndex); + remove(last); + + return true; + } + + public static Vector256 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static Vector256 fromHex(String hex) { + return translate.fromHex(hex); + } + public static Vector256 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + public static class Translator extends TypeTranslator { + @Override + public Vector256 fromParser(BinaryParser parser, Integer hint) { + Vector256 vector256 = new Vector256(); + if (hint == null) { + hint = parser.size() - parser.pos(); + } + for (int i = 0; i < hint / 32; i++) { + vector256.add(Hash256.fromParser(parser)); + } + + return vector256; + } + + public JSONArray toJSONArray(Vector256 obj) { + return obj.toJSONArray(); + } + + @Override + public Vector256 fromJSONArray(JSONArray jsonArray) { + Vector256 vector = new Vector256(); + + for (int i = 0; i < jsonArray.length(); i++) { + String hex = jsonArray.getString(i); + vector.add(new Hash256(B16.decode(hex))); + } + + return vector; + } + @Override + public Vector256 fromJacksonArray(ArrayNode jsonArray) { + Vector256 vector = new Vector256(); + + for (int i = 0; i < jsonArray.size(); i++) { + String hex = jsonArray.get(i).asText(); + vector.add(new Hash256(B16.decode(hex))); + } + + return vector; + } + } + static public Translator translate = new Translator(); + + public Vector256(){} + + public static Vector256Field vector256Field(final Field f) { + return new Vector256Field(){ @Override public Field getField() {return f;}}; + } + + static public Vector256Field Indexes = vector256Field(Field.Indexes); + static public Vector256Field Hashes = vector256Field(Field.Hashes); + static public Vector256Field Amendments = vector256Field(Field.Amendments); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java new file mode 100644 index 0000000000..560cce14a0 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java @@ -0,0 +1,68 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; + +import java.security.MessageDigest; + +public class HalfSha512 implements BytesSink { + private MessageDigest messageDigest; + + public HalfSha512() { + try { + messageDigest = MessageDigest.getInstance("SHA-512"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static HalfSha512 prefixed256(Prefix bytes) { + HalfSha512 halfSha512 = new HalfSha512(); + halfSha512.update(bytes); + return halfSha512; + } + + public void update(byte[] bytes) { + messageDigest.update(bytes); + } + + public void update(Hash256 hash) { + messageDigest.update(hash.bytes()); + } + + public MessageDigest digest() { + return messageDigest; + } + + public Hash256 finish() { + byte[] half = digestBytes(); + return new Hash256(half); + } + + private byte[] digestBytes() { + byte[] digest = messageDigest.digest(); + byte[] half = new byte[32]; + System.arraycopy(digest, 0, half, 0, 32); + return half; + } + + @Override + public void add(byte aByte) { + messageDigest.update(aByte); + } + + @Override + public void add(byte[] bytes) { + messageDigest.update(bytes); + } + + public void update(Prefix prefix) { + messageDigest.update(prefix.bytes()); + } + + public HalfSha512 add(SerializedType st) { + st.toBytesSink(this); + return this; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java new file mode 100644 index 0000000000..898d1b2913 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java @@ -0,0 +1,155 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; + +import java.math.BigInteger; +import java.util.Arrays; + +abstract public class Hash implements SerializedType, Comparable { + protected final byte[] hash; + + public Hash(byte[] bytes, int size) { + hash = checkHash(bytes, size); + } + + @Override + public String toString() { + return B16.encode(hash); + } + + @Override + public int hashCode() { + // Having this lazily computed and then cached would give significant + // performance boosts in some single threaded contexts. Given the inputs + // for the method are at least effectively final, and the method is + // essentially a pure function, it seems probably safe to do. It + // seems at worst, that in a multi threaded context, some extra work + // will be done in rare cases? + // TODO: check this assumption + return Arrays.hashCode(hash); + } + + private byte[] checkHash(byte[] bytes, int size) { + int length = bytes.length; + if (length > size) { + throwIllegalArg(length, "wide"); + } else if (length == size) { + // TODO: What costs for this ? + return bytes.clone(); + } else { + throwIllegalArg(length, "small"); + } + throw new IllegalStateException("Can not get here"); + } + + private void throwIllegalArg(int length, String wrongness) { + String simpleName = getClass().getSimpleName(); + throw new IllegalArgumentException("Hash length of " + length + "bytes is too " + + wrongness + + " for " + simpleName); + } + + BigInteger bigInteger() { + return new BigInteger(1, hash); + } + + // TODO: Is a defensive copy worthwhile? Or just be adults? Never been a + // problem in practice, though others may not know to avoid mutating the + // returned array. Pity Java doesn't have something like C++ const. + // If you did it in one place, should do it EVERY WHERE, inputs/outputs and + // on every type that stores mutable arrays internally and the perf and + // maybe memory (at least GC stress) costs could add up. + // It's a bit like polishing a tur*. + public byte[] bytes() { + return hash.clone(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Hash) { + return Arrays.equals(hash, ((Hash) obj).hash); + } + + return super.equals(obj); + } + + @Override + public int compareTo(Subclass another) { + byte[] thisBytes = bytes(); + byte[] bytes = another.bytes(); + + return compareBytes(thisBytes, bytes, 0, thisBytes.length); + } + + public int compareStartingAt(Subclass another, int start) { + byte[] thisBytes = bytes(); + byte[] bytes = another.bytes(); + + return compareBytes(thisBytes, bytes, start, thisBytes.length); + } + + private int compareBytes(byte[] thisBytes, byte[] bytes, int start, int numBytes) { + int thisLength = thisBytes.length; + if (!(bytes.length == thisLength)) { + throw new RuntimeException(); + } + + for (int i = start; i < numBytes; i++) { + int cmp = (thisBytes[i] & 0xFF) - (bytes[i] & 0xFF); + if (cmp != 0) { + return cmp < 0 ? -1 : 1; + } + } + return 0; + } + + public byte[] slice(int start) { + return slice(start, 0); + } + + public byte get(int i) { + if (i < 0) i += hash.length; + return hash[i]; + } + + private byte[] slice(int start, int end) { + if (start < 0) start += hash.length; + if (end <= 0) end += hash.length; + + int length = end - start; + byte[] slice = new byte[length]; + + System.arraycopy(hash, start, slice, 0, length); + return slice; + } + + static public abstract class HashTranslator extends TypeTranslator { + + public abstract T newInstance(byte[] b); + public abstract int byteWidth(); + + @Override + public T fromParser(BinaryParser parser, Integer hint) { + return newInstance(parser.read(byteWidth())); + } + + @Override + public Object toJSON(T obj) { + return B16.encode(obj.hash); + } + + @Override + public T fromString(String value) { + return newInstance(B16.decode(value)); + } + + @Override + public void toBytesSink(T obj, BytesSink to) { + to.add(obj.bytes()); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java new file mode 100644 index 0000000000..112340da9f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java @@ -0,0 +1,70 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Hash128Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; + +public class Hash128 extends Hash { + public Hash128(byte[] bytes) { + super(bytes, 16); + } + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.Hash128; + } + + public static Hash128 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static Hash128 fromHex(String string) { + return translate.fromHex(string); + } + public static Hash128 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + public static class Translator extends HashTranslator { + @Override + public Hash128 newInstance(byte[] b) { + return new Hash128(b); + } + + @Override + public int byteWidth() { + return 16; + } + } + + public static Translator translate = new Translator(); + + private static Hash128Field hash128Field(final Field f) { + return new Hash128Field(){ @Override public Field getField() {return f;}}; + } + + static public Hash128Field EmailHash = hash128Field(Field.EmailHash); + +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java new file mode 100644 index 0000000000..5f237c195c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java @@ -0,0 +1,81 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Hash160Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; + +public class Hash160 extends Hash { + public Hash160(byte[] bytes) { + super(bytes, 20); + } + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.Hash160; + } + + public static Hash160 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static Hash160 fromHex(String string) { + return translate.fromHex(string); + } + + public static Hash160 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + public static class Translator extends HashTranslator { + @Override + public Hash160 newInstance(byte[] b) { + return new Hash160(b); + } + + @Override + public int byteWidth() { + return 20; + } + + @Override + public Hash160 fromString(String value) { + if (value.startsWith("r")) { + return newInstance(AccountID.fromAddress(value).bytes()); + } + return super.fromString(value); + } + } + public static Translator translate = new Translator(); + + private static Hash160Field hash160Field(final Field f) { + return new Hash160Field(){ @Override public Field getField() {return f;}}; + } + + static public Hash160Field TakerPaysIssuer = hash160Field(Field.TakerPaysIssuer); + static public Hash160Field TakerGetsCurrency = hash160Field(Field.TakerGetsCurrency); + static public Hash160Field TakerPaysCurrency = hash160Field(Field.TakerPaysCurrency); + static public Hash160Field TakerGetsIssuer = hash160Field(Field.TakerGetsIssuer); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java new file mode 100644 index 0000000000..678b15ef00 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java @@ -0,0 +1,146 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Hash256Field; +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; + +import java.math.BigInteger; +import java.util.TreeMap; + +public class Hash256 extends Hash { + + public static final BigInteger bookBaseSize = new BigInteger("10000000000000000", 16); + + public int divergenceDepth(Hash256 other) { + return divergenceDepth(0, other); + } + public int divergenceDepth(int i, Hash256 other) { + for (; i < 64; i++) { + if (nibblet(i) != other.nibblet(i)) { + break; + } + } + return i; + } + + public static class Hash256Map extends TreeMap { + public Hash256Map(Hash256Map cache) { + super(cache); + } + public Hash256Map() { + + } + } + public static final Hash256 ZERO_256 = new Hash256(new byte[32]); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.Hash256; + } + + public boolean isZero() { + return this == Hash256.ZERO_256 || equals(Hash256.ZERO_256); + } + + public boolean isNonZero() { + return !isZero(); + } + + public static Hash256 fromHex(String s) { + return translate.fromHex(s); + } + public static Hash256 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + public static Hash256 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + public Hash256(byte[] bytes) { + super(bytes, 32); + } + + public static Hash256 signingHash(byte[] blob) { + return prefixedHalfSha512(HashPrefix.txSign, blob); + } + + public static Hash256 prefixedHalfSha512(Prefix prefix, byte[] blob) { + HalfSha512 messageDigest = HalfSha512.prefixed256(prefix); + messageDigest.update(blob); + return messageDigest.finish(); + } + + public int nibblet(int depth) { + int byte_ix = depth > 0 ? depth / 2 : 0; + int b = super.hash[byte_ix]; + if (depth % 2 == 0) { + b = (b & 0xF0) >> 4; + } else { + b = b & 0x0F; + } + return b; + } + + public static class Translator extends HashTranslator { + @Override + public Hash256 newInstance(byte[] b) { + return new Hash256(b); + } + + @Override + public int byteWidth() { + return 32; + } + } + public static Translator translate = new Translator(); + + public static Hash256Field hash256Field(final Field f) { + return new Hash256Field(){ @Override public Field getField() {return f;}}; + } + + static public Hash256Field LedgerHash = hash256Field(Field.LedgerHash); + static public Hash256Field ParentHash = hash256Field(Field.ParentHash); + static public Hash256Field TransactionHash = hash256Field(Field.TransactionHash); + static public Hash256Field AccountHash = hash256Field(Field.AccountHash); + static public Hash256Field PreviousTxnID = hash256Field(Field.PreviousTxnID); + static public Hash256Field AccountTxnID = hash256Field(Field.AccountTxnID); + static public Hash256Field LedgerIndex = hash256Field(Field.LedgerIndex); + static public Hash256Field WalletLocator = hash256Field(Field.WalletLocator); + static public Hash256Field RootIndex = hash256Field(Field.RootIndex); + static public Hash256Field BookDirectory = hash256Field(Field.BookDirectory); + static public Hash256Field InvoiceID = hash256Field(Field.InvoiceID); + static public Hash256Field Nickname = hash256Field(Field.Nickname); + static public Hash256Field Amendment = hash256Field(Field.Amendment); + static public Hash256Field TicketID = hash256Field(Field.TicketID); + static public Hash256Field Channel = hash256Field(Field.Channel); + static public Hash256Field CheckID = hash256Field(Field.CheckID); + static public Hash256Field Digest = hash256Field(Field.Digest); + static public Hash256Field ConsensusHash = hash256Field(Field.ConsensusHash); + + static public Hash256Field hash = hash256Field(Field.hash); + static public Hash256Field index = hash256Field(Field.index); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java new file mode 100644 index 0000000000..75a5900430 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java @@ -0,0 +1,159 @@ +package com.ripple.core.coretypes.hash; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Currency; +import com.ripple.core.coretypes.Issue; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.hash.prefixes.LedgerSpace; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; + +import java.util.Arrays; +import java.util.List; + +import static com.ripple.core.coretypes.hash.HalfSha512.prefixed256; +import static java.util.Collections.sort; + +public class Index { + private static Hash256 createBookBase(Issue pays, Issue gets) { + return prefixed256(LedgerSpace.bookDir) + .add(pays.currency()) + .add(gets.currency()) + .add(pays.issuer()) + .add(gets.issuer()) + .finish(); + } + + /** + * + * @return a copy of index, with quality overlaid in lowest 8 bytes + */ + public static Hash256 quality(Hash256 index, UInt64 quality) { + byte[] qi = new byte[32]; + System.arraycopy(index.bytes(), 0, qi, 0, 24); + if (quality != null) System.arraycopy(quality.toBytes(), 0, qi, 24, 8); + return new Hash256(qi); + } + + /** + * @return A copy of index, with the lowest 8 bytes all zeroed. + */ + private static Hash256 zeroQuality(Hash256 fullIndex) { + return quality(fullIndex, null); + } + + public static Hash256 rippleState(AccountID a1, AccountID a2, Currency currency) { + List accounts = Arrays.asList(a1, a2); + sort(accounts); + return rippleState(accounts, currency); + } + + public static Hash256 rippleState(List sortedAccounts, Currency currency) { + HalfSha512 hasher = prefixed256(LedgerSpace.ripple); + // Low then High + for (AccountID account : sortedAccounts) account.toBytesSink(hasher); + // Currency + currency.toBytesSink(hasher); + + return hasher.finish(); + } + + /** + * + * @param rootIndex The RootIndex index for the directory node + * @param nodeIndex nullable LowNode, HighNode, OwnerNode, BookNode etc + * defining a `page` number. + * + * @return A hash of rootIndex and nodeIndex when nodeIndex is non default + * else the rootIndex. This hash is used as an index for the next + * DirectoryNode page. + */ + public static Hash256 directoryNode(Hash256 rootIndex, UInt64 nodeIndex) { + if (nodeIndex == null || nodeIndex.isZero()) { + return rootIndex; + } + + return prefixed256(LedgerSpace.dirNode) + .add(rootIndex) + .add(nodeIndex) + .finish(); + } + + public static Hash256 accountRoot(AccountID accountID) { + return prefixed256(LedgerSpace.account).add(accountID).finish(); + } + + public static Hash256 paymentChannel(AccountID account, AccountID destination, UInt32 sequence) { + return prefixed256(LedgerSpace.paymentChannel) + .add(account) + .add(destination) + .add(sequence) + .finish(); + } + + public static Hash256 escrow(AccountID account, UInt32 sequence) { + return prefixed256(LedgerSpace.escrow) + .add(account) + .add(sequence) + .finish(); + } + + public static Hash256 ownerDirectory(AccountID account) { + return Hash256.prefixedHalfSha512(LedgerSpace.ownerDir, account.bytes()); + } + + public static Hash256 transactionID(byte[] blob) { + return Hash256.prefixedHalfSha512(HashPrefix.transactionID, blob); + } + + public static Hash256 bookStart(Issue pays, Issue gets) { + return zeroQuality(createBookBase(pays, gets)); + } + + public static Hash256 bookStart(Hash256 indexFromBookRange) { + return zeroQuality(indexFromBookRange); + } + + public static Hash256 bookEnd(Hash256 base) { + byte[] end = base.bigInteger().add(Hash256.bookBaseSize).toByteArray(); + if (end.length > 32) { + byte[] source = end; + end = new byte[32]; + System.arraycopy(source, source.length - 32, end, 0, 32); + } + return new Hash256(end); + } + + public static Hash256 ledgerHashes(long prev) { + return prefixed256(LedgerSpace.skipList) + .add(new UInt32(prev >> 16)) + .finish(); + } + public static Hash256 ledgerHashes() { + return prefixed256(LedgerSpace.skipList).finish(); + } + + public static Hash256 amendments() { + return prefixed256(LedgerSpace.amendment).finish(); + } + + public static Hash256 feeSettings() { + return prefixed256(LedgerSpace.fee).finish(); + } + + public static Hash256 signerList(AccountID account) { + return prefixed256(LedgerSpace.signerList) + .add(account) + .add(UInt32.ZERO) + .finish(); + } + + public static Hash256 ticket(AccountID account, UInt32 sequence) { + return prefixed256(LedgerSpace.ticket) + .add(account) + .add(sequence) + .finish(); + } + + +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java new file mode 100644 index 0000000000..f213d4eb38 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java @@ -0,0 +1,56 @@ +package com.ripple.core.coretypes.hash.prefixes; + +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.encodings.common.B16; + +/** + * The prefix codes are part of the Ripple protocol + * and existing codes cannot be arbitrarily changed. + */ +public enum HashPrefix implements Prefix { + transactionID ('T', 'X', 'N'), + txNode ('S', 'N', 'D'), + leafNode ('M', 'L', 'N'), + innerNode ('M', 'I', 'N'), + innerNodeV2 ('I', 'N', 'R'), + ledgerMaster ('L', 'W', 'R'), + txSign ('S', 'T', 'X'), + txMultiSign ('S', 'M', 'T'), + validation ('V', 'A', 'L'), + proposal ('P', 'R', 'P'), + manifest ('M', 'A', 'N'), + paymentChannelClaim ('C', 'L', 'M'); + + private UInt32 uInt32; + private byte[] bytes; + private String chars; + + @Override + public byte[] bytes() { + return bytes; + } + + public String toHex() { + return B16.encode(bytes); + } + + HashPrefix(char... chars) { + this.chars = new String(chars); + byte[] bytes = { + (byte) chars[0], + (byte) chars[1], + (byte) chars[2], + (byte) 0, + }; + uInt32 = UInt32.fromBytes(bytes); + this.bytes = bytes; + } + + public UInt32 uInt32() { + return uInt32; + } + + public String chars() { + return chars; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java new file mode 100644 index 0000000000..20f5d61388 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java @@ -0,0 +1,38 @@ +package com.ripple.core.coretypes.hash.prefixes; + +import com.ripple.core.coretypes.uint.UInt16; + +public enum LedgerSpace implements Prefix { + account('a'), + dirNode('d'), + generator('g'), + + ripple('r'), + offer('o'), // Entry for an offer. + ownerDir('O'), // Directory of things owned by an account. + bookDir('B'), // Directory of order books. + contract('c'), + skipList('s'), + escrow('u'), + amendment('f'), + fee('e'), + ticket('T'), + signerList('S'), + paymentChannel('x'), + + // no longer used + nickname('n'),; + + UInt16 uInt16; + public byte[] bytes; + + @Override + public byte[] bytes() { + return bytes; + } + + LedgerSpace(char c) { + uInt16 = new UInt16((int) c); + bytes = uInt16.toByteArray(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java new file mode 100644 index 0000000000..7ba8b7a62a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java @@ -0,0 +1,5 @@ +package com.ripple.core.coretypes.hash.prefixes; + +public interface Prefix { + byte[] bytes(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java new file mode 100644 index 0000000000..aae0dcedf3 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java @@ -0,0 +1,209 @@ +package com.ripple.core.coretypes.uint; + +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; +import com.ripple.utils.Utils; + +import java.math.BigInteger; + +abstract public class UInt extends Number implements SerializedType, Comparable { + private final BigInteger value; + + private static BigInteger[] upperBounds = new BigInteger[8]; + private static BigInteger maxUIntVal(int bits) { + return new BigInteger("2").pow(bits).subtract(BigInteger.ONE); + } + + static { + for (int i = 0; i < 8; i++) { + upperBounds[i] = maxUIntVal((i + 1) * 8 ); + } + } + + UInt(byte[] bytes) { + value = new BigInteger(1, bytes); + checkBounds(); + } + + private void checkBounds() { + BigInteger upper = upperBounds[getByteWidth() - 1]; + if (value.compareTo(upper) > 0 || value.compareTo(BigInteger.ZERO) < 0) { + throw new IllegalArgumentException("value `" + value + + "` is illegal for " + getClass().getSimpleName()); + } + } + + UInt(BigInteger bi) { + value = (bi); + checkBounds(); + } + UInt(Number s) { + value = (BigInteger.valueOf(s.longValue())); + checkBounds(); + } + UInt(String s) { + value = (new BigInteger(s)); + checkBounds(); + } + UInt(String s, int radix) { + value = (new BigInteger(s, radix)); + checkBounds(); + } + + @Override + public String toString() { + return value.toString(); + } + + public abstract int getByteWidth(); + protected abstract Subclass instanceFrom(BigInteger n); + + public Subclass add(UInt val) { + return instanceFrom(value.add(val.value)); + } + + public Subclass subtract(UInt val) { + return instanceFrom(value.subtract(val.value)); + } + + public Subclass multiply(UInt val) { + return instanceFrom(value.multiply(val.value)); + } + + public Subclass divide(UInt val) { + return instanceFrom(value.divide(val.value)); + } + + public Subclass or(UInt val) { + return instanceFrom(value.or(val.value)); + } + + public Subclass shiftLeft(int n) { + return instanceFrom(value.shiftLeft(n)); + } + + public Subclass shiftRight(int n) { + return instanceFrom(value.shiftRight(n)); + } + + public int compareTo(UInt val) { + return value.compareTo(val.value); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof UInt) { + return equals((UInt) obj); + } + else return super.equals(obj); + } + + public boolean equals(UInt x) { + return value.equals(x.value); + } + + public String toString(int radix) { + return value.toString(radix); + } + public byte[] toByteArray() { + int length = getByteWidth(); + return Utils.leadingZeroesTrimmedOrPaddedTo(length, value.toByteArray()); + } + + abstract public Object value(); + + public BigInteger bigInteger(){ + return value; + } + + @Override + public int intValue() { + return value.intValue(); + } + + @Override + public long longValue() { + return value.longValue(); + } + + @Override + public double doubleValue() { + return value.doubleValue(); + } + + @Override + public float floatValue() { + return value.floatValue(); + } + + @Override + public byte byteValue() { + return value.byteValue(); + } + + @Override + public short shortValue() { + return value.shortValue(); + } + + public boolean lte(T sequence) { + return compareTo(sequence) < 1; + } + + public boolean testBit(int f) { + // TODO, optimized ;) // move to Uint32 + return value.testBit(f); + } + + public boolean isZero() { + return value.signum() == 0; + } + + static public abstract class UINTTranslator extends TypeTranslator { + public abstract T newInstance(BigInteger i); + public abstract int byteWidth(); + + @Override + public T fromParser(BinaryParser parser, Integer hint) { + return newInstance(new BigInteger(1, parser.read(byteWidth()))); + } + + @Override + public Object toJSON(T obj) { + if (obj.getByteWidth() <= 4) { + return obj.longValue(); + } else { + return toString(obj); + } + } + + @Override + public T fromLong(long aLong) { + return newInstance(BigInteger.valueOf(aLong)); + } + + @Override + public T fromString(String value) { + int radix = byteWidth() <= 4 ? 10 : 16; + return newInstance(new BigInteger(value, radix)); + } + + @Override + public T fromInteger(int integer) { + return fromLong(integer); + } + + @Override + public String toString(T obj) { + return B16.encode(obj.toByteArray()); + } + + @Override + public void toBytesSink(T obj, BytesSink to) { + to.add(obj.toByteArray()); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java new file mode 100644 index 0000000000..9634cf6082 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java @@ -0,0 +1,106 @@ +package com.ripple.core.coretypes.uint; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.fields.UInt16Field; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.TypeTranslator; + +import java.math.BigInteger; + +public class UInt16 extends UInt { + public final static UInt16 ZERO = new UInt16(0); + + public static TypeTranslator translate = new UINTTranslator() { + @Override + public UInt16 newInstance(BigInteger i) { + return new UInt16(i); + } + + @Override + public int byteWidth() { + return 2; + } + }; + + public UInt16(byte[] bytes) { + super(bytes); + } + + public UInt16(BigInteger value) { + super(value); + } + + public UInt16(Number s) { + super(s); + } + + public UInt16(String s) { + super(s); + } + + public UInt16(String s, int radix) { + super(s, radix); + } + + public static UInt16 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static UInt16 fromHex(String string) { + return translate.fromHex(string); + } + + public static UInt16 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + @Override + public int getByteWidth() { + return 2; + } + + @Override + protected UInt16 instanceFrom(BigInteger n) { + return new UInt16(n); + } + + @Override + public Integer value() { + return intValue(); + } + + private static UInt16Field int16Field(final Field f) { + return new UInt16Field(){ @Override public Field getField() {return f;}}; + } + + static public UInt16Field LedgerEntryType = int16Field(Field.LedgerEntryType); + static public UInt16Field TransactionType = int16Field(Field.TransactionType); + static public UInt16Field SignerWeight = int16Field(Field.SignerWeight); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.UInt16; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java new file mode 100644 index 0000000000..b831c8607c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java @@ -0,0 +1,137 @@ +package com.ripple.core.coretypes.uint; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.fields.UInt32Field; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.TypeTranslator; + +import java.math.BigInteger; + +public class UInt32 extends UInt { + public final static UInt32 ZERO = new UInt32(0); + + public static TypeTranslator translate = new UINTTranslator() { + @Override + public UInt32 newInstance(BigInteger i) { + return new UInt32(i); + } + + @Override + public int byteWidth() { + return 4; + } + }; + + public UInt32(byte[] bytes) { + super(bytes); + } + + public UInt32(BigInteger value) { + super(value); + } + + public UInt32(Number val) { + super(val); + } + public UInt32(String s) { + super(s); + } + + public UInt32(String s, int radix) { + super(s, radix); + } + + public static UInt32 fromParser(BinaryParser binaryParser) { + return translate.fromParser(binaryParser); + } + public static UInt32 fromHex(String string) { + return translate.fromHex(string); + } + public static UInt32 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + @Override + public int getByteWidth() { + return 4; + } + + @Override + protected UInt32 instanceFrom(BigInteger n) { + return new UInt32(n); + } + + @Override + public Long value() { + return longValue(); + } + + private static UInt32Field int32Field(final Field f) { + return new UInt32Field(){ @Override public Field getField() {return f;}}; + } + + static public UInt32Field Flags = int32Field(Field.Flags); + static public UInt32Field SourceTag = int32Field(Field.SourceTag); + static public UInt32Field Sequence = int32Field(Field.Sequence); + static public UInt32Field PreviousTxnLgrSeq = int32Field(Field.PreviousTxnLgrSeq); + static public UInt32Field LedgerSequence = int32Field(Field.LedgerSequence); + static public UInt32Field CloseTime = int32Field(Field.CloseTime); + static public UInt32Field ParentCloseTime = int32Field(Field.ParentCloseTime); + static public UInt32Field SigningTime = int32Field(Field.SigningTime); + static public UInt32Field Expiration = int32Field(Field.Expiration); + static public UInt32Field TransferRate = int32Field(Field.TransferRate); + static public UInt32Field WalletSize = int32Field(Field.WalletSize); + static public UInt32Field OwnerCount = int32Field(Field.OwnerCount); + static public UInt32Field DestinationTag = int32Field(Field.DestinationTag); + static public UInt32Field HighQualityIn = int32Field(Field.HighQualityIn); + static public UInt32Field HighQualityOut = int32Field(Field.HighQualityOut); + static public UInt32Field LowQualityIn = int32Field(Field.LowQualityIn); + static public UInt32Field LowQualityOut = int32Field(Field.LowQualityOut); + static public UInt32Field QualityIn = int32Field(Field.QualityIn); + static public UInt32Field QualityOut = int32Field(Field.QualityOut); + static public UInt32Field StampEscrow = int32Field(Field.StampEscrow); + static public UInt32Field BondAmount = int32Field(Field.BondAmount); + static public UInt32Field LoadFee = int32Field(Field.LoadFee); + static public UInt32Field OfferSequence = int32Field(Field.OfferSequence); + static public UInt32Field FirstLedgerSequence = int32Field(Field.FirstLedgerSequence); + static public UInt32Field LastLedgerSequence = int32Field(Field.LastLedgerSequence); + static public UInt32Field TransactionIndex = int32Field(Field.TransactionIndex); + static public UInt32Field OperationLimit = int32Field(Field.OperationLimit); + static public UInt32Field ReferenceFeeUnits = int32Field(Field.ReferenceFeeUnits); + static public UInt32Field ReserveBase = int32Field(Field.ReserveBase); + static public UInt32Field ReserveIncrement = int32Field(Field.ReserveIncrement); + static public UInt32Field SetFlag = int32Field(Field.SetFlag); + static public UInt32Field ClearFlag = int32Field(Field.ClearFlag); + static public UInt32Field SignerQuorum = int32Field(Field.SignerQuorum); + public static UInt32Field SignerListID = int32Field(Field.SignerListID); + public static UInt32Field CancelAfter = int32Field(Field.CancelAfter); + public static UInt32Field FinishAfter = int32Field(Field.FinishAfter); + public static UInt32Field SettleDelay = int32Field(Field.SettleDelay); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.UInt32; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java new file mode 100644 index 0000000000..3312192542 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java @@ -0,0 +1,112 @@ +package com.ripple.core.coretypes.uint; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.fields.UInt64Field; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.TypeTranslator; + +import java.math.BigInteger; + +public class UInt64 extends UInt { + public final static UInt64 ZERO = new UInt64(0); + + public static TypeTranslator translate = new UINTTranslator() { + @Override + public UInt64 newInstance(BigInteger i) { + return new UInt64(i); + } + + @Override + public int byteWidth() { + return 8; + } + }; + + public UInt64(byte[] bytes) { + super(bytes); + } + + public UInt64(BigInteger value) { + super(value); + } + + public UInt64(Number s) { + super(s); + } + + public UInt64(String s) { + super(s); + } + + public UInt64(String s, int radix) { + super(s, radix); + } + + public static UInt64 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + + public static UInt64 fromHex(String string) { + return translate.fromHex(string); + } + public static UInt64 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + @Override + public int getByteWidth() { + return 8; + } + + @Override + protected UInt64 instanceFrom(BigInteger n) { + return new UInt64(n); + } + + @Override + public BigInteger value() { + return bigInteger(); + } + + private static UInt64Field int64Field(final Field f) { + return new UInt64Field(){ @Override public Field getField() {return f;}}; + } + + static public UInt64Field IndexNext = int64Field(Field.IndexNext); + static public UInt64Field IndexPrevious = int64Field(Field.IndexPrevious); + static public UInt64Field BookNode = int64Field(Field.BookNode); + static public UInt64Field OwnerNode = int64Field(Field.OwnerNode); + static public UInt64Field BaseFee = int64Field(Field.BaseFee); + static public UInt64Field ExchangeRate = int64Field(Field.ExchangeRate); + static public UInt64Field LowNode = int64Field(Field.LowNode); + static public UInt64Field HighNode = int64Field(Field.HighNode); + public static UInt64Field DestinationNode = int64Field(Field.DestinationNode); + public static UInt64Field Cookie = int64Field(Field.Cookie); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.UInt64; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java new file mode 100644 index 0000000000..528eaa8614 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java @@ -0,0 +1,105 @@ +package com.ripple.core.coretypes.uint; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; +import com.ripple.core.fields.UInt8Field; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.TypeTranslator; + +import java.math.BigInteger; + +public class UInt8 extends UInt { + public final static UInt8 ZERO = new UInt8(0); + + public static TypeTranslator translate = new UINTTranslator() { + @Override + public UInt8 newInstance(BigInteger i) { + return new UInt8(i); + } + + @Override + public int byteWidth() { + return 1; + } + }; + + public UInt8(byte[] bytes) { + super(bytes); + } + + public UInt8(BigInteger value) { + super(value); + } + + public UInt8(Number s) { + super(s); + } + + public UInt8(String s) { + super(s); + } + + public UInt8(String s, int radix) { + super(s, radix); + } + + public static UInt8 fromParser(BinaryParser parser) { + return translate.fromParser(parser); + } + public static UInt8 fromHex(String hex) { + return translate.fromHex(hex); + } + public static UInt8 fromBytes(byte[] bytes) { + return translate.fromBytes(bytes); + } + + @Override + public int getByteWidth() { + return 1; + } + + @Override + protected UInt8 instanceFrom(BigInteger n) { + return new UInt8(n); + } + + @Override + public Short value() { + return shortValue(); + } + + private static UInt8Field int8Field(final Field f) { + return new UInt8Field() {@Override public Field getField() {return f; } }; + } + + static public UInt8Field CloseResolution = int8Field(Field.CloseResolution); + static public UInt8Field Method = int8Field(Field.Method); + static public UInt8Field TransactionResult = int8Field(Field.TransactionResult); + static public UInt8Field TickSize = int8Field(Field.TickSize); + + @Override + public Object toJSON() { + return translate.toJSON(this); + } + + @Override + public byte[] toBytes() { + return translate.toBytes(this); + } + + @Override + public String toHex() { + return translate.toHex(this); + } + + @Override + public void toBytesSink(BytesSink to) { + translate.toBytesSink(this, to); + } + + @Override + public Type type() { + return Type.UInt8; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java b/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java new file mode 100644 index 0000000000..99f18b5309 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java @@ -0,0 +1,29 @@ +package com.ripple.core.enums; + +// Ledger Specific Flags +public class LedgerFlag { + public static int + // ltACCOUNT_ROOT + PasswordSpent = 0x00010000, // True, if password set fee is spent. + RequireDestTag = 0x00020000, // True, to require a DestinationTag for payments. + RequireAuth = 0x00040000, // True, to require a authorization to hold IOUs. + DisallowXRP = 0x00080000, // True, to disallow sending XRP. + DisableMaster = 0x00100000, // True, force regular key + NoFreeze = 0x00200000, // True, cannot freeze ripple states + GlobalFreeze = 0x00400000, // True, all assets frozen + DefaultRipple = 0x00800000, // True, all assets frozen + + // ltOFFER + Passive = 0x00010000, + Sell = 0x00020000, // True, offer was placed as a sell. + + // ltRIPPLE_STATE + LowReserve = 0x00010000, // True, if entry counts toward reserve. + HighReserve = 0x00020000, + LowAuth = 0x00040000, + HighAuth = 0x00080000, + LowNoRipple = 0x00100000, + HighNoRipple = 0x00200000, + LowFreeze = 0x00400000, // True, low side has set freeze flag + HighFreeze = 0x00800000; // True, high side has set freeze flag +} diff --git a/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java b/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java new file mode 100644 index 0000000000..adb7f9e910 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java @@ -0,0 +1,50 @@ +package com.ripple.core.enums; + +// Transaction Specific Flags +public class TransactionFlag { + public static long + FullyCanonicalSig = 0x80000000L, + Universal = FullyCanonicalSig, + UniversalMask = ~Universal, + + // AccountSet flags: + RequireDestTag = 0x00010000, + OptionalDestTag = 0x00020000, + RequireAuth = 0x00040000, + OptionalAuth = 0x00080000, + DisallowXRP = 0x00100000, + AllowXRP = 0x00200000, + AccountSetMask = ~(Universal | RequireDestTag | OptionalDestTag + | RequireAuth | OptionalAuth + | DisallowXRP | AllowXRP), + + // AccountSet SetFlag/ClearFlag values + asfRequireDest = 1, + asfRequireAuth = 2, + asfDisallowXRP = 3, + asfDisableMaster = 4, + asfAccountTxnID = 5, + asfNoFreeze = 6, + asfGlobalFreeze = 7, + + // OfferCreate flags: + Passive = 0x00010000, + ImmediateOrCancel = 0x00020000, + FillOrKill = 0x00040000, + Sell = 0x00080000, + OfferCreateMask = ~(Universal | Passive | ImmediateOrCancel | FillOrKill | Sell), + + // Payment flags: + NoRippleDirect = 0x00010000, + PartialPayment = 0x00020000, + LimitQuality = 0x00040000, + PaymentMask = ~(Universal | PartialPayment | LimitQuality | NoRippleDirect), + + // TrustSet flags: + SetAuth = 0x00010000, + SetNoRipple = 0x00020000, + ClearNoRipple = 0x00040000, + SetFreeze = 0x00100000, + ClearFreeze = 0x00200000, + TrustSetMask = ~(Universal | SetAuth | SetNoRipple | ClearNoRipple | SetFreeze | ClearFreeze); +} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java b/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java new file mode 100644 index 0000000000..f31e3df14d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class AccountIDField implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java b/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java new file mode 100644 index 0000000000..4666ff51f9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class AmountField implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java b/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java new file mode 100644 index 0000000000..2925c89611 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class BlobField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Field.java new file mode 100644 index 0000000000..87871ecca0 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Field.java @@ -0,0 +1,328 @@ +package com.ripple.core.fields; + +import java.util.*; + +public enum Field { + // These are all presorted (verified in a static block below) + // They can then be used in a TreeMap, using the Enum (private) ordinal + // comparator + Generic(0, Type.Unknown), + Invalid(-1, Type.Unknown), + + LedgerEntryType(1, Type.UInt16), + TransactionType(2, Type.UInt16), + SignerWeight(3, Type.UInt16), + + Flags(2, Type.UInt32), + SourceTag(3, Type.UInt32), + Sequence(4, Type.UInt32), + PreviousTxnLgrSeq(5, Type.UInt32), + LedgerSequence(6, Type.UInt32), + CloseTime(7, Type.UInt32), + ParentCloseTime(8, Type.UInt32), + SigningTime(9, Type.UInt32), + Expiration(10, Type.UInt32), + TransferRate(11, Type.UInt32), + WalletSize(12, Type.UInt32), + OwnerCount(13, Type.UInt32), + DestinationTag(14, Type.UInt32), + + HighQualityIn(16, Type.UInt32), + HighQualityOut(17, Type.UInt32), + LowQualityIn(18, Type.UInt32), + LowQualityOut(19, Type.UInt32), + QualityIn(20, Type.UInt32), + QualityOut(21, Type.UInt32), + StampEscrow(22, Type.UInt32), + BondAmount(23, Type.UInt32), + LoadFee(24, Type.UInt32), + OfferSequence(25, Type.UInt32), + FirstLedgerSequence(26, Type.UInt32), // Deprecated: do not use + // Added new semantics in 9486fc416ca7c59b8930b734266eed4d5b714c50 + LastLedgerSequence(27, Type.UInt32), + TransactionIndex(28, Type.UInt32), + OperationLimit(29, Type.UInt32), + ReferenceFeeUnits(30, Type.UInt32), + ReserveBase(31, Type.UInt32), + ReserveIncrement(32, Type.UInt32), + SetFlag(33, Type.UInt32), + ClearFlag(34, Type.UInt32), + SignerQuorum(35, Type.UInt32), + CancelAfter(36, Type.UInt32), + FinishAfter(37, Type.UInt32), + SignerListID(38, Type.UInt32), + SettleDelay(39, Type.UInt32), + + IndexNext(1, Type.UInt64), + IndexPrevious(2, Type.UInt64), + BookNode(3, Type.UInt64), + OwnerNode(4, Type.UInt64), + BaseFee(5, Type.UInt64), + ExchangeRate(6, Type.UInt64), + LowNode(7, Type.UInt64), + HighNode(8, Type.UInt64), + DestinationNode(9, Type.UInt64), + Cookie(10, Type.UInt64), + + EmailHash(1, Type.Hash128), + + LedgerHash(1, Type.Hash256), + ParentHash(2, Type.Hash256), + TransactionHash(3, Type.Hash256), + AccountHash(4, Type.Hash256), + PreviousTxnID(5, Type.Hash256), + LedgerIndex(6, Type.Hash256), + WalletLocator(7, Type.Hash256), + RootIndex(8, Type.Hash256), + // Added in rippled commit: 9486fc416ca7c59b8930b734266eed4d5b714c50 + AccountTxnID(9, Type.Hash256), + BookDirectory(16, Type.Hash256), + InvoiceID(17, Type.Hash256), + Nickname(18, Type.Hash256), + Amendment(19, Type.Hash256), + TicketID(20, Type.Hash256), + Digest(21, Type.Hash256), + Channel(22, Type.Hash256), + ConsensusHash(23, Type.Hash256), + CheckID(24, Type.Hash256), + + hash(257, Type.Hash256), + index(258, Type.Hash256), + + Amount(1, Type.Amount), + Balance(2, Type.Amount), + LimitAmount(3, Type.Amount), + TakerPays(4, Type.Amount), + TakerGets(5, Type.Amount), + LowLimit(6, Type.Amount), + HighLimit(7, Type.Amount), + Fee(8, Type.Amount), + SendMax(9, Type.Amount), + DeliverMin(10, Type.Amount), + + MinimumOffer(16, Type.Amount), + RippleEscrow(17, Type.Amount), + // Added in rippled commit: e7f0b8eca69dd47419eee7b82c8716b3aa5a9e39 + DeliveredAmount(18, Type.Amount), + // These are auxiliary fields +// quality(257, Type.AMOUNT), + taker_gets_funded(258, Type.Amount), + taker_pays_funded(259, Type.Amount), + + PublicKey(1, Type.Blob), + MessageKey(2, Type.Blob), + SigningPubKey(3, Type.Blob), + TxnSignature(4, Type.Blob), + Signature(6, Type.Blob), + Domain(7, Type.Blob), + FundCode(8, Type.Blob), + RemoveCode(9, Type.Blob), + ExpireCode(10, Type.Blob), + CreateCode(11, Type.Blob), + MemoType(12, Type.Blob), + MemoData(13, Type.Blob), + MemoFormat(14, Type.Blob), + Fulfillment(16, Type.Blob), + Condition(17, Type.Blob), + MasterSignature(18, Type.Blob), + + Account(1, Type.AccountID), + Owner(2, Type.AccountID), + Destination(3, Type.AccountID), + Issuer(4, Type.AccountID), + Authorize(5, Type.AccountID), + Unauthorize(6, Type.AccountID), + Target(7, Type.AccountID), + RegularKey(8, Type.AccountID), + + ObjectEndMarker(1, Type.STObject), + + TransactionMetaData(2, Type.STObject), + CreatedNode(3, Type.STObject), + DeletedNode(4, Type.STObject), + ModifiedNode(5, Type.STObject), + PreviousFields(6, Type.STObject), + FinalFields(7, Type.STObject), + NewFields(8, Type.STObject), + TemplateEntry(9, Type.STObject), + Memo(10, Type.STObject), + SignerEntry(11, Type.STObject), + Signer(16, Type.STObject), + // 17 unused + Majority(18, Type.STObject), + + ArrayEndMarker(1, Type.STArray), +// SigningAccounts(2, Type.STArray), + Signers(3, Type.STArray), + SignerEntries(4, Type.STArray), + Template(5, Type.STArray), + Necessary(6, Type.STArray), + Sufficient(7, Type.STArray), + AffectedNodes(8, Type.STArray), + Memos(9, Type.STArray), + Majorities(16, Type.STArray), + + CloseResolution(1, Type.UInt8), + Method(2, Type.UInt8), + TransactionResult(3, Type.UInt8), + TickSize(16, Type.UInt8), + + TakerPaysCurrency(1, Type.Hash160), + TakerPaysIssuer(2, Type.Hash160), + TakerGetsCurrency(3, Type.Hash160), + TakerGetsIssuer(4, Type.Hash160), + + Paths(1, Type.PathSet), + + Indexes(1, Type.Vector256), + Hashes(2, Type.Vector256), + Amendments(3, Type.Vector256), + + Transaction(1, Type.Transaction), + LedgerEntry(1, Type.LedgerEntry), + Validation(1, Type.Validation); + + final int id; + + // defaults + boolean signingField = true; + boolean isSerialized = true; + boolean isVlEncoded = false; + + public static Field fromString(String key) { + Field f; + try { + f = valueOf(key); + } catch (IllegalArgumentException e) { + f = null; + } + return f; + } + + private static byte[] asBytes(Field field) { + int name = field.getId(), type = field.getType().getId(); + ArrayList header = new ArrayList<>(3); + + if (type < 16) + { + if (name < 16) // common type, common name + header.add((byte)((type << 4) | name)); + else + { + // common type, uncommon name + header.add((byte)(type << 4)); + header.add((byte)(name)); + } + } + else if (name < 16) + { + // uncommon type, common name + header.add((byte)(name)); + header.add((byte)(type)); + } + else + { + // uncommon type, uncommon name + header.add((byte)(0)); + header.add((byte)(type)); + header.add((byte)(name)); + } + + byte[] headerBytes = new byte[header.size()]; + for (int i = 0; i < header.size(); i++) { + headerBytes[i] = header.get(i); + } + + return headerBytes; + } + + public int getId() { + return id; + } + + final int code; + final Type type; + private final byte[] bytes; + public Object tag = null; + + Field(int fid, Type tid) { + id = fid; + type = tid; + code = (type.id << 16) | fid; + isSerialized = isSerialized(this); + + if (isSerialized()) { + bytes = asBytes(this); + } else { + bytes = null; + } + } + + static private Map byCode = new TreeMap<>(); + + static public Field fromCode(Integer integer) { + return byCode.get(integer); + } + + public Type getType() { + return type; + } + + public boolean isSerialized() { + return isSerialized; + } + public boolean isVLEncoded() { + return isVlEncoded; + } + public boolean isSigningField() { + return signingField; + } + private static boolean isSerialized(Field f) { + // This should screen out `hash` and `index` and the like + return ((f.type.id > 0) && (f.type.id < 256) && (f.id > 0) && (f.id < 256)); + } + + static public Comparator comparator = Comparator.comparingInt(o -> o.code); + + static { + for (Field f : Field.values()) { + byCode.put(f.code, f); + f.isSerialized = isSerialized(f); + f.signingField = f.isSerialized; + + switch (f.type) { + case Blob: + case AccountID: + case Vector256: + f.isVlEncoded = true; + break; + default: + break; + } + + } + + TxnSignature.signingField = false; + Signers.signingField = false; + Signature.signingField = false; + MasterSignature.signingField = false; + + ArrayList sortedFields; + Field[] values = Field.values(); + sortedFields = new ArrayList<>(Arrays.asList(values)); + sortedFields.sort(comparator); + + for (int i = 0; i < values.length; i++) { + Field av = values[i]; + Field lv = sortedFields.get(i); + if (av.code != lv.code) { + throw new AssertionError( + "Field enum declaration isn't presorted"); + } + } + } + + public byte[] getBytes() { + return bytes; + } +} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/fields/HasField.java b/ripple-core/src/main/java/com/ripple/core/fields/HasField.java new file mode 100644 index 0000000000..edc49029a3 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/HasField.java @@ -0,0 +1,5 @@ +package com.ripple.core.fields; + +public interface HasField { + Field getField(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java new file mode 100644 index 0000000000..b8b78e912e --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class Hash128Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java new file mode 100644 index 0000000000..f0569b13eb --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class Hash160Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java new file mode 100644 index 0000000000..e0a83b67ef --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class Hash256Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java b/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java new file mode 100644 index 0000000000..5982570eb6 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class PathSetField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java b/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java new file mode 100644 index 0000000000..056a55c861 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class STArrayField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java b/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java new file mode 100644 index 0000000000..c802f57a2a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class STObjectField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Type.java b/ripple-core/src/main/java/com/ripple/core/fields/Type.java new file mode 100644 index 0000000000..2384861e88 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Type.java @@ -0,0 +1,35 @@ +/* DO NOT EDIT, AUTO GENERATED */ +package com.ripple.core.fields; + +public enum Type { + Unknown(-2), + Done(-1), + NotPresent(0), + UInt16(1), + UInt32(2), + UInt64(3), + Hash128(4), + Hash256(5), + Amount(6), + Blob(7), + AccountID(8), + STObject(14), + STArray(15), + UInt8(16), + Hash160(17), + PathSet(18), + Vector256(19), + Transaction(10001), + LedgerEntry(10002), + Validation(10003); + + final int id; + + Type(int type) { + this.id = type; + } + + public int getId() { + return id; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java new file mode 100644 index 0000000000..fa99de6499 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class UInt16Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java new file mode 100644 index 0000000000..a2b58902c2 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class UInt32Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java new file mode 100644 index 0000000000..3c85f3b312 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class UInt64Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java new file mode 100644 index 0000000000..465a1ad6be --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class UInt8Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java new file mode 100644 index 0000000000..7cadc88ea8 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java @@ -0,0 +1,3 @@ +package com.ripple.core.fields; + +public abstract class Vector256Field implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/Format.java b/ripple-core/src/main/java/com/ripple/core/formats/Format.java new file mode 100644 index 0000000000..0061213330 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/formats/Format.java @@ -0,0 +1,66 @@ +package com.ripple.core.formats; + +import com.ripple.core.fields.Field; + +import java.util.EnumMap; + +abstract public class Format { + protected Format() { + } + + protected void addCommonFields(){} + + EnumMap requirementEnumMap = new EnumMap<>(Field.class); + EnumMap common = new EnumMap<>(Field.class); + + public EnumMap requirements() { + return requirementEnumMap; + } + + abstract public String name (); + + public Format(Object[] args) { + if ((!(args.length % 2 == 0)) || args.length < 2) { + throw new IllegalArgumentException("Varargs length should be a minimum multiple of 2"); + } + for (int i = 0; i < args.length; i+= 2) { + Field f = (Field) args[i]; + Requirement r = (Requirement) args[i + 1]; + put(f, r); + } + } + + protected void put(Field f, Requirement r) { + requirementEnumMap.put(f, r); + } + + @SuppressWarnings("unchecked") + Subclass required(Field f) { + put(f, Requirement.REQUIRED); + return (Subclass) this; + } + + @SuppressWarnings("unchecked") + Subclass optional(Field f) { + put(f, Requirement.OPTIONAL); + return (Subclass) this; + } + + @SuppressWarnings("unchecked") + Subclass nonDefault(Field f) { + put(f, Requirement.DEFAULT); + return (Subclass) this; + } + + public boolean isCommon(Field field) { + return common.containsKey(field); + } + + public static enum Requirement { + INVALID(-1), + REQUIRED( 0), + OPTIONAL( 1), + DEFAULT( 2); + Requirement(int i) {} + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java b/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java new file mode 100644 index 0000000000..2dbd576593 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java @@ -0,0 +1,230 @@ +package com.ripple.core.formats; + +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; + +import java.util.EnumMap; + +public class LEFormat extends Format { + static public EnumMap formats = new EnumMap(LedgerEntryType.class); + { + common.put(Field.LedgerIndex, Requirement.OPTIONAL); + common.put(Field.LedgerEntryType, Requirement.REQUIRED); + common.put(Field.Flags, Requirement.REQUIRED); + } + + static public LEFormat fromString(String name) { + return getLedgerFormat(LedgerEntryType.valueOf(name)); + } + + static public LEFormat fromNumber(Number ord) { + return getLedgerFormat(LedgerEntryType.fromNumber(ord)); + } + + static public LEFormat fromValue(Object o) { + if (o instanceof Number) { + return fromNumber(((Number) o).intValue()); + } else if (o instanceof String){ + return fromString((String) o); + } + else { + return null; + } + } + + public static LEFormat getLedgerFormat(LedgerEntryType key) { + if (key == null) return null; + return formats.get(key); + } + + public final LedgerEntryType ledgerEntryType; + + public LEFormat(LedgerEntryType type, Object... args) { + super(args); + ledgerEntryType = type; + addCommonFields(); + formats.put(type, this); + } + + public LEFormat(LedgerEntryType type) { + super(); + ledgerEntryType = type; + addCommonFields(); + formats.put(type, this); + } + + @Override + protected void addCommonFields() { + requirementEnumMap.putAll(common); + } + + @Override + public String name() { + return ledgerEntryType.toString(); + } + + public static LEFormat AccountRoot = new LEFormat( + LedgerEntryType.AccountRoot, + Field.Account, Requirement.REQUIRED, + Field.Sequence, Requirement.REQUIRED, + Field.Balance, Requirement.REQUIRED, + Field.OwnerCount, Requirement.REQUIRED, + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED, + Field.AccountTxnID, Requirement.OPTIONAL, + Field.RegularKey, Requirement.OPTIONAL, + Field.EmailHash, Requirement.OPTIONAL, + Field.WalletLocator, Requirement.OPTIONAL, + Field.WalletSize, Requirement.OPTIONAL, + Field.MessageKey, Requirement.OPTIONAL, + Field.TransferRate, Requirement.OPTIONAL, + Field.Domain, Requirement.OPTIONAL, + Field.TickSize, Requirement.OPTIONAL + ); + + public static LEFormat DirectoryNode = new LEFormat( + LedgerEntryType.DirectoryNode, + Field.Owner, Requirement.OPTIONAL, // for owner directories + Field.TakerPaysCurrency, Requirement.OPTIONAL, // for order book directories + Field.TakerPaysIssuer, Requirement.OPTIONAL, // for order book directories + Field.TakerGetsCurrency, Requirement.OPTIONAL, // for order book directories + Field.TakerGetsIssuer, Requirement.OPTIONAL, // for order book directories + Field.ExchangeRate, Requirement.OPTIONAL, // for order book directories + Field.Indexes, Requirement.REQUIRED, + Field.RootIndex, Requirement.REQUIRED, + Field.IndexNext, Requirement.OPTIONAL, + Field.IndexPrevious, Requirement.OPTIONAL + ); + + + public static LEFormat Offer = new LEFormat( + LedgerEntryType.Offer, + Field.Account, Requirement.REQUIRED, + Field.Sequence, Requirement.REQUIRED, + Field.TakerPays, Requirement.REQUIRED, + Field.TakerGets, Requirement.REQUIRED, + Field.BookDirectory, Requirement.REQUIRED, + Field.BookNode, Requirement.REQUIRED, + Field.OwnerNode, Requirement.REQUIRED, + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED, + Field.Expiration, Requirement.OPTIONAL + ); + + public static LEFormat Ticket = new LEFormat( + LedgerEntryType.Ticket, + Field.Account, Requirement.REQUIRED, + Field.Sequence, Requirement.REQUIRED, + Field.OwnerNode, Requirement.REQUIRED, + Field.Target, Requirement.OPTIONAL, + Field.Expiration, Requirement.OPTIONAL + ); + + public static LEFormat RippleState = new LEFormat( + LedgerEntryType.RippleState, + Field.Balance, Requirement.REQUIRED, + Field.LowLimit, Requirement.REQUIRED, + Field.HighLimit, Requirement.REQUIRED, + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED, + Field.LowNode, Requirement.OPTIONAL, + Field.LowQualityIn, Requirement.OPTIONAL, + Field.LowQualityOut, Requirement.OPTIONAL, + Field.HighNode, Requirement.OPTIONAL, + Field.HighQualityIn, Requirement.OPTIONAL, + Field.HighQualityOut, Requirement.OPTIONAL + ); + + public static LEFormat Escrow = new LEFormat( + LedgerEntryType.Escrow, + Field.Account, Requirement.REQUIRED, + Field.Destination, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED, + Field.OwnerNode, Requirement.REQUIRED, + + Field.Condition, Requirement.OPTIONAL, + Field.CancelAfter, Requirement.OPTIONAL, + Field.FinishAfter, Requirement.OPTIONAL, + Field.SourceTag, Requirement.OPTIONAL, + Field.DestinationTag, Requirement.OPTIONAL, + Field.DestinationNode, Requirement.OPTIONAL + ); + + public static LEFormat LedgerHashes = new LEFormat( + LedgerEntryType.LedgerHashes, + Field.FirstLedgerSequence, Requirement.OPTIONAL, // Remove if we do a ledger restart + Field.LastLedgerSequence, Requirement.OPTIONAL, + Field.Hashes, Requirement.REQUIRED + ); + + public static LEFormat Amendments = new LEFormat( + LedgerEntryType.Amendments, + Field.Amendments, Requirement.OPTIONAL, + Field.Majorities, Requirement.OPTIONAL + ); + + public static LEFormat SignerList = new LEFormat( + LedgerEntryType.SignerList, + + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED, + Field.OwnerNode, Requirement.REQUIRED, + + Field.SignerQuorum, Requirement.REQUIRED, + Field.SignerEntries, Requirement.REQUIRED, + Field.SignerListID, Requirement.REQUIRED + ); + + public static LEFormat FeeSettings = new LEFormat( + LedgerEntryType.FeeSettings, + Field.BaseFee, Requirement.REQUIRED, + Field.ReferenceFeeUnits, Requirement.REQUIRED, + Field.ReserveBase, Requirement.REQUIRED, + Field.ReserveIncrement, Requirement.REQUIRED + ); + + public static LEFormat PayChannel = new LEFormat( + LedgerEntryType.PayChannel, + Field.Account, Requirement.REQUIRED, + Field.Destination, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + Field.Balance, Requirement.REQUIRED, + Field.PublicKey, Requirement.REQUIRED, + Field.SettleDelay, Requirement.REQUIRED, + Field.Expiration, Requirement.OPTIONAL, + Field.CancelAfter, Requirement.OPTIONAL, + Field.SourceTag, Requirement.OPTIONAL, + Field.DestinationTag, Requirement.OPTIONAL, + Field.OwnerNode, Requirement.REQUIRED, + Field.PreviousTxnID, Requirement.REQUIRED, + Field.PreviousTxnLgrSeq, Requirement.REQUIRED + ); + + public static LEFormat Check = new LEFormat(LedgerEntryType.Check) + .required(Field.PreviousTxnID) + .required(Field.PreviousTxnLgrSeq) + .required(Field.Account) + .required(Field.Destination) + .required(Field.SendMax) + .required(Field.Sequence) + .required(Field.OwnerNode) + .required(Field.DestinationNode) + .optional(Field.Expiration) + .optional(Field.InvoiceID) + .optional(Field.SourceTag) + .optional(Field.DestinationTag) + + ; + + public static LEFormat DepositPreauth = new LEFormat(LedgerEntryType.DepositPreauth) + .required(Field.Account) + .required(Field.Authorize) + .required(Field.OwnerNode) + .required(Field.PreviousTxnID) + .required(Field.PreviousTxnLgrSeq) + ; + +} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java b/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java new file mode 100644 index 0000000000..fa66d27533 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java @@ -0,0 +1,212 @@ +package com.ripple.core.formats; + +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.TransactionType; + +import java.util.EnumMap; + +public class TxFormat extends Format { + static public EnumMap formats = new EnumMap<>(TransactionType.class); + { + common.put(Field.TransactionType, Requirement.REQUIRED); + common.put(Field.Account, Requirement.REQUIRED); + common.put(Field.Sequence, Requirement.REQUIRED); + common.put(Field.Fee, Requirement.REQUIRED); + common.put(Field.SigningPubKey, Requirement.REQUIRED); + + common.put(Field.Flags, Requirement.OPTIONAL); + common.put(Field.SourceTag, Requirement.OPTIONAL); + common.put(Field.PreviousTxnID, Requirement.OPTIONAL); + common.put(Field.OperationLimit, Requirement.OPTIONAL); + common.put(Field.TxnSignature, Requirement.OPTIONAL); + common.put(Field.AccountTxnID, Requirement.OPTIONAL); + common.put(Field.LastLedgerSequence, Requirement.OPTIONAL); + common.put(Field.Memos, Requirement.OPTIONAL); + common.put(Field.Signers, Requirement.OPTIONAL); + + } + public final TransactionType transactionType; + + static public TxFormat fromString(String name) { + return getTxFormat(TransactionType.valueOf(name)); + } + + static public TxFormat fromNumber(Number ord) { + return getTxFormat(TransactionType.fromNumber(ord)); + } + + private static TxFormat getTxFormat(TransactionType key) { + if (key == null) return null; + return formats.get(key); + } + + public TxFormat(TransactionType type, Object... args) { + super(args); + transactionType = type; + addCommonFields(); + formats.put(transactionType, this); + } + + public TxFormat(TransactionType type) { + super(); + transactionType = type; + addCommonFields(); + formats.put(transactionType, this); + } + + @Override + protected void addCommonFields() { + requirementEnumMap.putAll(common); + } + + @Override + public String name() { + return transactionType.toString(); + } + + private static TxFormat makeFormat(TransactionType tt) { + return new TxFormat(tt); + } + + static public TxFormat AccountSet = makeFormat( + TransactionType.AccountSet) + .optional(Field.EmailHash) + .optional(Field.EmailHash) + .optional(Field.WalletLocator) + .optional(Field.WalletSize) + .optional(Field.MessageKey) + .optional(Field.Domain) + .optional(Field.TransferRate) + .optional(Field.SetFlag) + .optional(Field.TickSize) + .optional(Field.ClearFlag); + + static public TxFormat TrustSet = new TxFormat( + TransactionType.TrustSet, + Field.LimitAmount, Requirement.OPTIONAL, + Field.QualityIn, Requirement.OPTIONAL, + Field.QualityOut, Requirement.OPTIONAL); + + static public TxFormat OfferCreate = new TxFormat( + TransactionType.OfferCreate, + Field.TakerPays, Requirement.REQUIRED, + Field.TakerGets, Requirement.REQUIRED, + Field.Expiration, Requirement.OPTIONAL, + Field.OfferSequence, Requirement.OPTIONAL); + + static public TxFormat OfferCancel = new TxFormat( + TransactionType.OfferCancel, + Field.OfferSequence, Requirement.REQUIRED); + + static public TxFormat TicketCreate = new TxFormat( + TransactionType.TicketCreate, + Field.Target, Requirement.OPTIONAL, + Field.Expiration, Requirement.OPTIONAL); + + static public TxFormat TicketCancel = new TxFormat( + TransactionType.TicketCancel, + Field.TicketID, Requirement.REQUIRED); + + static public TxFormat SetRegularKey = new TxFormat( + TransactionType.SetRegularKey, + Field.RegularKey, Requirement.OPTIONAL); + + static public TxFormat Payment = new TxFormat( + TransactionType.Payment, + Field.Destination, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + Field.SendMax, Requirement.OPTIONAL, + Field.Paths, Requirement.DEFAULT, + Field.InvoiceID, Requirement.OPTIONAL, + Field.DestinationTag, Requirement.OPTIONAL, + Field.DeliverMin, Requirement.OPTIONAL + ); + + + static public TxFormat EscrowCreate = new TxFormat( + TransactionType.EscrowCreate, + Field.Destination, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + Field.Condition, Requirement.OPTIONAL, + Field.CancelAfter, Requirement.OPTIONAL, + Field.FinishAfter, Requirement.OPTIONAL, + Field.DestinationTag, Requirement.OPTIONAL); + + static public TxFormat EscrowFinish = new TxFormat( + TransactionType.EscrowFinish, + Field.Owner, Requirement.REQUIRED, + Field.OfferSequence, Requirement.REQUIRED, + Field.Fulfillment, Requirement.OPTIONAL, + Field.Condition, Requirement.OPTIONAL); + + static public TxFormat EscrowCancel = new TxFormat( + TransactionType.EscrowCancel, + Field.Owner, Requirement.REQUIRED, + Field.OfferSequence, Requirement.REQUIRED); + + static public TxFormat EnableAmendment = new TxFormat( + TransactionType.EnableAmendment, + Field.LedgerSequence, Requirement.REQUIRED, + Field.Amendment, Requirement.REQUIRED); + + static public TxFormat SetFee = new TxFormat( + TransactionType.SetFee, + Field.BaseFee, Requirement.REQUIRED, + Field.ReferenceFeeUnits, Requirement.REQUIRED, + Field.ReserveBase, Requirement.REQUIRED, + Field.LedgerSequence, Requirement.OPTIONAL, + Field.ReserveIncrement, Requirement.REQUIRED + ); + + static public TxFormat SignerListSet = new TxFormat( + TransactionType.SignerListSet, + Field.SignerQuorum, Requirement.REQUIRED, + Field.SignerEntries, Requirement.OPTIONAL + ); + static public TxFormat PaymentChannelCreate = new TxFormat( + TransactionType.PaymentChannelCreate, + Field.Destination, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + Field.SettleDelay, Requirement.REQUIRED, + Field.PublicKey, Requirement.REQUIRED, + Field.CancelAfter, Requirement.OPTIONAL, + Field.DestinationTag, Requirement.OPTIONAL + ); + static public TxFormat PaymentChannelFund = new TxFormat( + TransactionType.PaymentChannelFund, + Field.Channel, Requirement.REQUIRED, + Field.Amount, Requirement.REQUIRED, + Field.Expiration, Requirement.OPTIONAL + ); + static public TxFormat PaymentChannelClaim = new TxFormat( + TransactionType.PaymentChannelClaim, + Field.Channel, Requirement.REQUIRED, + Field.Amount, Requirement.OPTIONAL, + Field.Balance, Requirement.OPTIONAL, + Field.Signature, Requirement.OPTIONAL, + Field.PublicKey, Requirement.OPTIONAL + ); + + static public TxFormat CheckCreate = new TxFormat(TransactionType.CheckCreate) + .required(Field.Destination) + .required(Field.SendMax) + .optional(Field.Expiration) + .optional(Field.DestinationTag) + .optional(Field.InvoiceID) + ; + + static public TxFormat CheckCash = new TxFormat(TransactionType.CheckCash) + .required(Field.CheckID) + .optional(Field.Amount) + .optional(Field.DeliverMin) + ; + + static public TxFormat CheckCancel = new TxFormat(TransactionType.CheckCancel) + .required(Field.CheckID) + ; + + static public TxFormat DepositPreauth = new TxFormat(TransactionType.DepositPreauth) + .optional(Field.Authorize) + .optional(Field.Unauthorize) + ; +} diff --git a/ripple-core/src/main/java/com/ripple/core/runtime/Value.java b/ripple-core/src/main/java/com/ripple/core/runtime/Value.java new file mode 100644 index 0000000000..1f69e88c55 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/runtime/Value.java @@ -0,0 +1,111 @@ +package com.ripple.core.runtime; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.List; +import java.util.Map; + +public enum Value { + UNKNOWN, + STRING, + JSON_OBJECT, + JSON_ARRAY, + + JACKSON_ARRAY, + JACKSON_BINARY, + JACKSON_BOOLEAN, + JACKSON_MISSING, + JACKSON_NULL, + JACKSON_NUMBER, + JACKSON_OBJECT, + JACKSON_POJO, + JACKSON_STRING, + + LIST, + MAP, + NUMBER, + BYTE, + DOUBLE, + FLOAT, + INTEGER, + LONG, + BYTE_ARRAY, + SHORT, + BOOLEAN; + + static public Value typeOf (Object object) { + if (object instanceof String) { + return STRING; + } + else if (object instanceof Number) { + if (object instanceof Byte) { + return BYTE; + } + else if (object instanceof Double) { + return DOUBLE; + } + else if (object instanceof Float) { + return FLOAT; + } + else if (object instanceof Integer) { + return INTEGER; + } + else if (object instanceof Long) { + return LONG; + } + else if (object instanceof Short) { + return SHORT; + } + return NUMBER; + } + else if (object instanceof JSONObject) { + return JSON_OBJECT; + } + else if (object instanceof JSONArray) { + return JSON_ARRAY; + } + else if (object instanceof JsonNode) { + JsonNode node = (JsonNode) object; + JsonNodeType nodeType = node.getNodeType(); + switch (nodeType) { + case ARRAY: + return JACKSON_ARRAY; + case BINARY: + return JACKSON_BINARY; + case BOOLEAN: + return JACKSON_BOOLEAN; + case MISSING: + return JACKSON_MISSING; + case NULL: + return JACKSON_NULL; + case NUMBER: + return JACKSON_NUMBER; + case OBJECT: + return JACKSON_OBJECT; + case POJO: + return JACKSON_POJO; + case STRING: + return JACKSON_STRING; + } + throw new IllegalStateException("unknown node type"); + } + else if (object instanceof Map) { + return MAP; + } + else if (object instanceof Boolean) { + return BOOLEAN; + } + else if (object instanceof List) { + return LIST; + } + else if (object instanceof byte[]) { + return BYTE_ARRAY; + } + else { + return UNKNOWN; + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java b/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java new file mode 100644 index 0000000000..86fa08a7d9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java @@ -0,0 +1,99 @@ +package com.ripple.core.serialized; + +import com.ripple.core.fields.Field; +import com.ripple.encodings.common.B16; + +public class BinaryParser { + protected final int size; + protected byte[] bytes; + protected int cursor = 0; + + public BinaryParser(byte[] bytes) { + this.size = bytes.length; + this.bytes = bytes; + } + + public BinaryParser(int size) { + this.size = size; + } + + public BinaryParser(String hex) { + this(B16.decode(hex)); + } + + public void skip(int n) { + cursor += n; + } + public byte readOne() { + return bytes[cursor++]; + } + public byte[] read(int n) { + byte[] ret = new byte[n]; + System.arraycopy(bytes, cursor, ret, 0, n); + cursor += n; +// } + return ret; + } + + public Field readField() { + int fieldCode = readFieldCode(); + Field field = Field.fromCode(fieldCode); + if (field == null) { + throw new IllegalStateException("Couldn't parse field from " + + Integer.toHexString(fieldCode)); + } + return field; + } + + public int readFieldCode() { + byte tagByte = readOne(); + + int typeBits = (tagByte & 0xFF) >>> 4; + if (typeBits == 0) typeBits = readOne(); + + int fieldBits = tagByte & 0x0F; + if (fieldBits == 0) fieldBits = readOne(); + + return (typeBits << 16 | fieldBits); + } + + public boolean end() { + return cursor >= size; // greater guard against infinite loops + } + + public int pos() { + return cursor; + } + + public int readOneInt() { + return readOne() & 0xFF; + } + + public int readVLLength() { + int b1 = readOneInt(); + int result; + + if (b1 <= 192) { + result = b1; + } else if (b1 <= 240) { + int b2 = readOneInt(); + result = 193 + (b1 - 193) * 256 + b2; + } else if (b1 <= 254) { + int b2 = readOneInt(); + int b3 = readOneInt(); + result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3; + } else { + throw new RuntimeException("Invalid varint length indicator"); + } + + return result; + } + + public int size() { + return size; + } + + public boolean end(Integer customEnd) { + return cursor >= size || customEnd != null && cursor >= customEnd; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java b/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java new file mode 100644 index 0000000000..1b39a2ac10 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java @@ -0,0 +1,94 @@ +package com.ripple.core.serialized; + +import com.ripple.core.fields.Field; +import com.ripple.core.fields.Type; + +import java.util.Arrays; + +public class BinarySerializer { + private final BytesSink sink; + + public BinarySerializer(BytesSink sink) { + this.sink = sink; + } + + public void add(byte[] n) { + sink.add(n); + } + + public void addLengthEncoded(byte[] n) { + add(encodeVL(n.length)); + add(n); + } + + public static byte[] encodeVL(int length) { + // TODO: bytes + byte[] lenBytes = new byte[4]; + + if (length <= 192) + { + lenBytes[0] = (byte) (length); + return Arrays.copyOf(lenBytes, 1); + } + else if (length <= 12480) + { + length -= 193; + lenBytes[0] = (byte) (193 + (length >>> 8)); + lenBytes[1] = (byte) (length & 0xff); + return Arrays.copyOf(lenBytes, 2); + } + else if (length <= 918744) { + length -= 12481; + lenBytes[0] = (byte) (241 + (length >>> 16)); + lenBytes[1] = (byte) ((length >> 8) & 0xff); + lenBytes[2] = (byte) (length & 0xff); + return Arrays.copyOf(lenBytes, 3); + } else { + throw new RuntimeException("Overflow error"); + } + } + + public void add(BytesList bl) { + for (byte[] bytes : bl.rawList()) { + sink.add(bytes); + } + } + + public int addFieldHeader(Field f) { + if (!f.isSerialized()) { + throw new IllegalStateException(String.format("Field %s is a discardable field", f)); + } + byte[] n = f.getBytes(); + add(n); + return n.length; + } + + public void add(byte type) { + sink.add(type); + } + + public void addLengthEncoded(BytesList bytes) { + add(encodeVL(bytes.bytesLength())); + add(bytes); + } + + public void add(Field field, SerializedType value) { + addFieldHeader(field); + if (field.isVLEncoded()) { + addLengthEncoded(value); + } else { + value.toBytesSink(sink); + if (field.getType() == Type.STObject) { + addFieldHeader(Field.ObjectEndMarker); + } else if (field.getType() == Type.STArray) { + addFieldHeader(Field.ArrayEndMarker); + } + } + } + + public void addLengthEncoded(SerializedType value) { + BytesList bytes = new BytesList(); + value.toBytesSink(bytes); + addLengthEncoded(bytes); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java b/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java new file mode 100644 index 0000000000..69d150aa16 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java @@ -0,0 +1,77 @@ +package com.ripple.core.serialized; + +import java.security.MessageDigest; +import java.util.ArrayList; + +public class BytesList implements BytesSink { + private ArrayList buffer = new ArrayList(); + + private int len = 0; + + public void add(BytesList bl) { + for (byte[] bytes : bl.rawList()) { + add(bytes); + } + } + + @Override + public void add(byte aByte) { + add(new byte[]{aByte}); + } + + @Override + public void add(byte[] bytes) { + len += bytes.length; + buffer.add(bytes); + } + + public byte[] bytes() { + int n = bytesLength(); + byte[] bytes = new byte[n]; + addBytes(bytes, 0); + return bytes; + } + + static public String[] hexLookup = new String[256]; + static { + for (int i = 0; i < 256; i++) { + String s = Integer.toHexString(i).toUpperCase(); + if (s.length() == 1) { + s = "0" + s; + } + hexLookup[i] = s; + } + } + + public String bytesHex() { + StringBuilder builder = new StringBuilder(len * 2); + for (byte[] buf : buffer) { + for (byte aBytes : buf) { + builder.append(hexLookup[aBytes & 0xFF]); + } + } + return builder.toString(); + } + + public int bytesLength() { + return len; + } + + private int addBytes(byte[] bytes, int destPos) { + for (byte[] buf : buffer) { + System.arraycopy(buf, 0, bytes, destPos, buf.length); + destPos += buf.length; + } + return destPos; + } + + public void updateDigest(MessageDigest digest) { + for (byte[] buf : buffer) { + digest.update(buf); + } + } + + public ArrayList rawList() { + return buffer; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java new file mode 100644 index 0000000000..7ec5c6cc5a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java @@ -0,0 +1,8 @@ +package com.ripple.core.serialized; + +public interface BytesSink { + default void add(byte aByte) { + add(new byte[] {aByte}); + } + void add(byte[] bytes); +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java new file mode 100644 index 0000000000..02de05e311 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java @@ -0,0 +1,16 @@ +package com.ripple.core.serialized; + +public class MultiSink implements BytesSink { + final private BytesSink[] sinks; + public MultiSink(BytesSink... sinks) { + this.sinks = sinks; + } + @Override + public void add(byte b) { + for (BytesSink sink : sinks) sink.add(b); + } + @Override + public void add(byte[] b) { + for (BytesSink sink : sinks) sink.add(b); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java b/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java new file mode 100644 index 0000000000..1b5263e935 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java @@ -0,0 +1,11 @@ +package com.ripple.core.serialized; + +import com.ripple.core.fields.Type; + +public interface SerializedType { + Object toJSON(); + byte[] toBytes(); + String toHex(); + void toBytesSink(BytesSink to); + Type type(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java b/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java new file mode 100644 index 0000000000..b3f964c31d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java @@ -0,0 +1,81 @@ +package com.ripple.core.serialized; + +import java.io.*; +import java.util.zip.GZIPInputStream; + +public class StreamBinaryParser extends BinaryParser { + final BufferedInputStream stream; + + public StreamBinaryParser(InputStream stream, long size) { + super((int) size); + this.stream = new BufferedInputStream(stream); + } + + private static boolean isGZip(File fio) { + return fio.getName().endsWith("gz"); + } + private static int getUncompressedSize(File fio) { + if (isGZip(fio)) { + int val; + try { + RandomAccessFile raf = new RandomAccessFile(fio, "r"); + raf.seek(raf.length() - 4); + int b4 = raf.read(); + int b3 = raf.read(); + int b2 = raf.read(); + int b1 = raf.read(); + val = (b1 << 24) | (b2 << 16) + (b3 << 8) + b4; + raf.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return val; + } else { + return (int) fio.length(); + } + } + + public void skip(int n) { + try { + long skipped = stream.skip(n); + if (skipped != n) { + throw new RuntimeException("Expected to skip more bytes"); + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public byte readOne() { + return read(1)[0]; + } + public byte[] read(int n) { + byte[] ret = new byte[n]; + try { + int read = stream.read(ret); + if (read != n) { + throw new RuntimeException("Expected to read more bytes"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + cursor += n; + return ret; + } + public static StreamBinaryParser fromFile(String path) { + try { + File f = new File(path); + FileInputStream fstream = new FileInputStream(path); + InputStream stream = fstream; + long s = fstream.getChannel().size(); + + if (isGZip(f)) { + s = getUncompressedSize(f); + stream = new GZIPInputStream(fstream); + } + return new StreamBinaryParser(stream, s); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java new file mode 100644 index 0000000000..34fe16d377 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java @@ -0,0 +1,31 @@ +package com.ripple.core.serialized; + +import java.io.IOException; +import java.io.OutputStream; + +public class StreamSink implements BytesSink { + OutputStream out; + + public StreamSink(OutputStream out) { + this.out = out; + } + + @Override + public void add(byte aByte) { + try { + out.write(aByte); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void add(byte[] bytes) { + try { + out.write(bytes); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} + diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java b/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java new file mode 100644 index 0000000000..4bd988338b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java @@ -0,0 +1,151 @@ + +package com.ripple.core.serialized; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.runtime.Value; +import com.ripple.encodings.common.B16; +import org.json.JSONArray; +import org.json.JSONObject; + +/** + * @param The SerializedType class + * TODO, this should only really have methods that each class over-rides + * it's currently pretty NASTY + */ +public abstract class TypeTranslator { + + @SuppressWarnings("unchecked") + public T fromValue(Object object) { + switch (Value.typeOf(object)) { + case STRING: + return fromString((String) object); + case JACKSON_ARRAY: + return fromJacksonArray((ArrayNode) object); + case JACKSON_BINARY: + throw new IllegalStateException("cant handle jackson binary"); + case JACKSON_BOOLEAN: + return fromBoolean(((JsonNode) object).asBoolean()); + case JACKSON_MISSING: + throw new IllegalStateException("cant create from missing"); + case JACKSON_NULL: + throw new IllegalStateException("cant create from null"); + case JACKSON_NUMBER: + JsonNode node = (JsonNode) object; + if (node.isLong()) { + return fromLong(node.asLong()); + } else if (node.isInt()) { + return fromInteger(node.asInt()); + } else if (node.isDouble()) { + return fromDouble(node.asDouble()); + } else if (node.isFloat()) { + return fromDouble(node.floatValue()); + } + throw new IllegalStateException("cant create from null"); + case JACKSON_OBJECT: + return fromJacksonObject((ObjectNode) object); + case JACKSON_POJO: + throw new IllegalStateException("cant handle POJO"); + case JACKSON_STRING: + return fromString(((JsonNode) object).asText()); + case DOUBLE: + return fromDouble((Double) object); + case INTEGER: + return fromInteger((Integer) object); + case LONG: + return fromLong((Long) object); + case BOOLEAN: + return fromBoolean((Boolean) object); + case JSON_ARRAY: + return fromJSONArray((JSONArray) object); + case JSON_OBJECT: + return fromJSONObject((JSONObject) object); + case BYTE_ARRAY: + return fromBytes((byte[]) object); + case UNKNOWN: + default: + return (T) object; + } + + } + + protected T fromJacksonObject(ObjectNode object) { + throw new UnsupportedOperationException(); + } + + protected T fromJacksonArray(ArrayNode node) { + throw new UnsupportedOperationException(); + } + + public String toString(T obj) { + return obj.toString(); + } + + protected T fromJSONObject(JSONObject jsonObject) { + throw new UnsupportedOperationException(); + } + + protected T fromJSONArray(JSONArray jsonArray) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("WeakerAccess") + protected T fromBoolean(boolean aBoolean) { + throw new UnsupportedOperationException(); + } + + protected T fromLong(long aLong) { + throw new UnsupportedOperationException(); + } + + protected T fromInteger(int integer) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("WeakerAccess") + protected T fromDouble(double aDouble) { + throw new UnsupportedOperationException(); + } + + protected T fromString(String value) { + throw new UnsupportedOperationException(); + } + + /** + * @param hint Using a boxed integer, allowing null for no hint + */ + public abstract T fromParser(BinaryParser parser, Integer hint); + + public T fromParser(BinaryParser parser) { + return fromParser(parser, null); + } + + public T fromBytes(byte[] b) { + return fromParser(new BinaryParser(b)); + } + + public T fromHex(String hex) { + return fromBytes(B16.decode(hex)); + } + + public Object toJSON(T obj) { + return obj.toJSON(); + } + + public void toBytesSink(T obj, BytesSink to) { + obj.toBytesSink(to); + } + + public byte[] toBytes(T obj) { + BytesList to = new BytesList(); + toBytesSink(obj, to); + return to.bytes(); + } + + public String toHex(T obj) { + BytesList to = new BytesList(); + toBytesSink(obj, to); + return to.bytesHex(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java new file mode 100644 index 0000000000..dafd5d761a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java @@ -0,0 +1,258 @@ +package com.ripple.core.serialized.enums; + +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; + +import java.util.TreeMap; + +class Holder { + public static int ords = 0; +} + +public enum EngineResult implements SerializedType { + telLOCAL_ERROR(-399, "Local failure."), + telBAD_DOMAIN("Domain too long."), + telBAD_PATH_COUNT("Malformed: Too many paths."), + telBAD_PUBLIC_KEY("Public key too long."), + telFAILED_PROCESSING("Failed to correctly process transaction."), + telINSUF_FEE_P("Fee insufficient."), + telNO_DST_PARTIAL("Partial payment to create account not allowed."), + + telCAN_NOT_QUEUE("Can not queue at this time."), + telCAN_NOT_QUEUE_BALANCE("Can not queue at this time: insufficient balance to pay all queued fees."), + telCAN_NOT_QUEUE_BLOCKS("Can not queue at this time: would block later queued transaction(s)."), + + telCAN_NOT_QUEUE_BLOCKED("Can not queue at this time: blocking transaction in queue."), + telCAN_NOT_QUEUE_FEE("Can not queue at this time: fee insufficient to replace queued transaction."), + telCAN_NOT_QUEUE_FULL("Can not queue at this time: queue is full."), + + temMALFORMED(-299, "Malformed transaction."), + temBAD_AMOUNT("Can only send positive amounts."), + temBAD_CURRENCY("Malformed: Bad currency."), + temBAD_EXPIRATION("Malformed: Bad expiration."), + temBAD_FEE("Invalid fee, negative or not XRP."), + temBAD_ISSUER("Malformed: Bad issuer."), + temBAD_LIMIT("Limits must be non-negative."), + temBAD_OFFER("Malformed: Bad offer."), + temBAD_PATH("Malformed: Bad path."), + temBAD_PATH_LOOP("Malformed: Loop in path."), + temBAD_SEND_XRP_LIMIT("Malformed: Limit quality is not allowed for XRP to XRP."), + temBAD_SEND_XRP_MAX("Malformed: Send max is not allowed for XRP to XRP."), + temBAD_SEND_XRP_NO_DIRECT("Malformed: No Ripple direct is not allowed for XRP to XRP."), + temBAD_SEND_XRP_PARTIAL("Malformed: Partial payment is not allowed for XRP to XRP."), + temBAD_SEND_XRP_PATHS("Malformed: Paths are not allowed for XRP to XRP."), + temBAD_SEQUENCE("Malformed: Sequence is not in the past."), + temBAD_SIGNATURE("Malformed: Bad signature."), + temBAD_SRC_ACCOUNT("Malformed: Bad source account."), + temBAD_TRANSFER_RATE("Malformed: Transfer rate must be >= 1.0 and <= 2.0"), + temDST_IS_SRC("Destination may not be source."), + temDST_NEEDED("Destination not specified."), + temINVALID("The transaction is ill-formed."), + temINVALID_FLAG("The transaction has an invalid flag."), + temREDUNDANT("Sends same currency to self."), + temRIPPLE_EMPTY("PathSet with no paths."), + temDISABLED("The transaction requires logic that is currently disabled."), + temBAD_SIGNER("Malformed: No signer may duplicate account or other signers."), + temBAD_QUORUM("Malformed: Quorum is unreachable."), + temBAD_WEIGHT("Malformed: Weight must be a positive value."), + temBAD_TICK_SIZE("Malformed: Tick size out of range."), + temINVALID_ACCOUNT_ID("Malformed: A field contains an invalid account ID."), + temCANNOT_PREAUTH_SELF("Malformed: An account may not preauthorize itself."), + temUNCERTAIN("In process of determining result. Never returned."), + temUNKNOWN(-266, "The transaction requires logic that is not implemented yet."), + + tefFAILURE(-199, "Failed to apply."), + tefALREADY("The exact transaction was already in this ledger."), + tefBAD_ADD_AUTH("Not authorized to add account."), + tefBAD_AUTH("Transaction's public key is not authorized."), + tefBAD_LEDGER("Ledger in unexpected state."), + tefCREATED("Can't add an already created account."), + tefEXCEPTION("Unexpected program state."), + tefINTERNAL("Internal error."), + tefNO_AUTH_REQUIRED("Auth is not required."), + tefPAST_SEQ("This sequence number has already passed."), + tefWRONG_PRIOR("This previous transaction does not match."), + tefMASTER_DISABLED("Master key is disabled."), + tefMAX_LEDGER("Ledger sequence too high."), + tefBAD_SIGNATURE("A signature is provided for a non-signer."), + tefBAD_QUORUM("Signatures provided do not meet the quorum."), + tefNOT_MULTI_SIGNING("Account has no appropriate list of multi-signers."), + tefBAD_AUTH_MASTER("Auth for unclaimed account needs correct master key."), + tefINVARIANT_FAILED("Fee claim violated invariants for the transaction."), + + + + + terRETRY(-99, "Retry transaction."), + terFUNDS_SPENT("Can't set password, password set funds already spent."), + terINSUF_FEE_B("Account balance can't pay fee."), + terNO_ACCOUNT("The source account does not exist."), + terNO_AUTH("Not authorized to hold IOUs."), + terNO_LINE("No such line."), + terOWNERS("Non-zero owner count."), + terPRE_SEQ("Missing/inapplicable prior transaction."), + terLAST("Process last."), + terNO_RIPPLE("Path does not permit rippling."), + terQUEUED("Held until escalated fee drops."), + + tesSUCCESS(0, "The transaction was applied. Only final in a validated ledger."), + + tecCLAIM(100, "Fee claimed. Sequence used. No action."), + tecPATH_PARTIAL(101, "Path could not send full amount."), + tecUNFUNDED_ADD(102, "Insufficient XRP balance for WalletAdd."), + tecUNFUNDED_OFFER(103, "Insufficient balance to fund created offer."), + tecUNFUNDED_PAYMENT(104, "Insufficient XRP balance to send."), + tecFAILED_PROCESSING(105, "Failed to correctly process transaction."), + tecDIR_FULL(121, "Can not add entry to full directory."), + tecINSUF_RESERVE_LINE(122, "Insufficient reserve to add trust line."), + tecINSUF_RESERVE_OFFER(123, "Insufficient reserve to create offer."), + tecNO_DST(124, "Destination does not exist. Send XRP to create it."), + tecNO_DST_INSUF_XRP(125, "Destination does not exist. Too little XRP sent to create it."), + tecNO_LINE_INSUF_RESERVE(126, "No such line. Too little reserve to create it."), + tecNO_LINE_REDUNDANT(127, "Can't set non-existent line to default."), + tecPATH_DRY(128, "Path could not send partial amount."), + tecUNFUNDED(129, "One of _ADD, _OFFER, or _SEND. Deprecated."), + tecNO_ALTERNATIVE_KEY(130, "The operation would remove the ability to sign transactions with the account."), + tecNO_REGULAR_KEY(131, "Regular key is not set."), + tecOWNERS(132, "Non-zero owner count."), + tecNO_ISSUER(133, "Issuer account does not exist."), + tecNO_AUTH(134, "Not authorized to hold asset."), + tecNO_LINE(135, "No such line."), + tecINSUFF_FEE(136, "Insufficient balance to pay fee."), + tecFROZEN(137, "Asset is frozen."), + tecNO_TARGET(138, "Target account does not exist."), + tecNO_PERMISSION(139, "No permission to perform requested operation."), + tecNO_ENTRY(140, "No matching entry found."), + tecINSUFFICIENT_RESERVE(141, "Insufficient reserve to complete requested operation."), + tecNEED_MASTER_KEY(142, "The operation requires the use of the Master Key."), + tecDST_TAG_NEEDED(143, "A destination tag is required."), + tecINTERNAL(144, "An internal error has occurred during processing."), + tecOVERSIZE(145, "Object exceeded serialization limits."), + tecCRYPTOCONDITION_ERROR(146, "Malformed, invalid, or mismatched conditional or fulfillment."), + tecINVARIANT_FAILED(147, "One or more invariants for the transaction were not satisfied."), + tecEXPIRED(148, "Expiration time is passed."), + tecDUPLICATE(149, "Ledger object already exists."), + tecKILLED(150, "FillOrKill offer killed."), + ; + + + public int asInteger() { + return ord; + } + + @Override + public Type type() { + return Type.UInt8; + } + + private static int ords = 0; + int ord; + public String human; + EngineResult class_ = null; + + EngineResult(Integer i, String s) { + human = s; + if (i == null) { + i = ++Holder.ords; + } else { + Holder.ords = i; + } + ord = i; + } + + EngineResult(String s) { + this(null, s); + } + + private static TreeMap byCode; + + static { + byCode = new TreeMap<>(); + for (EngineResult ter : EngineResult.values()) { + byCode.put(ter.ord, ter); + } + } + + public static EngineResult fromNumber(Number i) { + return byCode.get(i.intValue()); + } + + + /*Serialized Type implementation*/ + @Override + public byte[] toBytes() { + return new byte[]{(byte) ord}; + } + + @Override + public void toBytesSink(BytesSink to) { + to.add((byte) ord); + } + + @Override + public Object toJSON() { + return toString(); + } + + @Override + public String toHex() { + return B16.encode(toBytes()); + } + + public static class Translator extends TypeTranslator { + @Override + public EngineResult fromParser(BinaryParser parser, Integer hint) { + return fromInteger(parser.readOneInt()); + } + + @Override + public EngineResult fromString(String value) { + return EngineResult.valueOf(value); + } + + @Override + public EngineResult fromInteger(int integer) { + return fromNumber(integer); + } + } + + @SuppressWarnings("unused") + public static Translator translate = new Translator(); + + // Result Classes + public static EngineResult resultClass(EngineResult result) { + if (result.ord >= telLOCAL_ERROR.ord && result.ord < temMALFORMED.ord) { + return telLOCAL_ERROR; + } + if (result.ord >= temMALFORMED.ord && result.ord < tefFAILURE.ord) { + return temMALFORMED; + } + if (result.ord >= tefFAILURE.ord && result.ord < terRETRY.ord) { + return tefFAILURE; + } + if (result.ord >= terRETRY.ord && result.ord < tesSUCCESS.ord) { + return terRETRY; + } + if (result.ord >= tesSUCCESS.ord && result.ord < tecCLAIM.ord) { + return tesSUCCESS; + } + return tecCLAIM; + } + + public EngineResult resultClass() { + return class_; + } + + static { + for (EngineResult engineResult : EngineResult.values()) { + engineResult.class_ = resultClass(engineResult); + } + } + +} + + diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java new file mode 100644 index 0000000000..cba003d2d9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java @@ -0,0 +1,101 @@ +package com.ripple.core.serialized.enums; + +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +public enum LedgerEntryType implements SerializedType { + // Invalid (-1), + AccountRoot('a'), + DirectoryNode('d'), + // GeneratorMap ('g'), + RippleState('r'), + Escrow('u'), + // Nickname ('n'), // deprecated + Offer('o'), + // Contract ('c'), + LedgerHashes('h'), + Amendments('f'), + FeeSettings('s'), + Ticket('T'), + SignerList('S'), + PayChannel('x'), + Check('C'), + DepositPreauth('p'); + + final int ord; + + LedgerEntryType(int i) { + ord = i; + } + + static private Map byCode = new TreeMap<>(); + + static { + for (Object a : LedgerEntryType.values()) { + LedgerEntryType f = (LedgerEntryType) a; + byCode.put(f.ord, f); + } + } + + @Override + public Type type() { + return Type.UInt16; + } + + public static LedgerEntryType fromNumber(Number i) { + return byCode.get(i.intValue()); + } + + public Integer asInteger() { + return ord; + } + + // SeralizedType interface + @Override + public byte[] toBytes() { + return new byte[]{(byte) ((ord >>> 8) & 0xFF), (byte) (ord & 0xFF)}; + } + + @Override + public Object toJSON() { + return toString(); + } + + @Override + public String toHex() { + return B16.encode(toBytes()); + } + + @Override + public void toBytesSink(BytesSink to) { + to.add(toBytes()); + } + + public static class Translator extends TypeTranslator { + @Override + public LedgerEntryType fromParser(BinaryParser parser, Integer hint) { + return fromNumber(parser.readOneInt() << 8 | parser.readOneInt()); + } + + @Override + public LedgerEntryType fromInteger(int integer) { + return fromNumber(integer); + } + + @Override + public LedgerEntryType fromString(String value) { + return LedgerEntryType.valueOf(value); + } + } + + @SuppressWarnings("unused") + public static Translator translate = new Translator(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java new file mode 100644 index 0000000000..7c98c3da07 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java @@ -0,0 +1,103 @@ +package com.ripple.core.serialized.enums; + +import com.ripple.core.fields.Type; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.TypeTranslator; +import com.ripple.encodings.common.B16; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +public enum TransactionType implements SerializedType { + // Invalid (-1), + Payment (0), + EscrowCreate (1), // open + EscrowFinish (2), + AccountSet (3), // open, + EscrowCancel (4), + SetRegularKey(5), + // unused1 (6), // open + OfferCreate (7), + OfferCancel (8), + // unused2(9), + TicketCreate(10), + TicketCancel(11), + SignerListSet(12), + PaymentChannelCreate(13), + PaymentChannelFund(14), + PaymentChannelClaim(15), + CheckCreate(16), + CheckCash(17), + CheckCancel(18), + DepositPreauth(19), + TrustSet (20), + EnableAmendment(100), + SetFee(101); + + public int asInteger() { + return ord; + } + + final int ord; + TransactionType(int i) { + ord = i; + } + + @Override + public Type type() { + return Type.UInt16; + } + + static private Map byCode = new TreeMap<>(); + static { + for (Object a : TransactionType.values()) { + TransactionType f = (TransactionType) a; + byCode.put(f.ord, f); + } + } + + static public TransactionType fromNumber(Number i) { + return byCode.get(i.intValue()); + } + + // SeralizedType interface + @Override + public byte[] toBytes() { + // TODO: bytes + return new byte[]{(byte) (ord >> 8), (byte) (ord & 0xFF)}; + } + @Override + public Object toJSON() { + return toString(); + } + @Override + public String toHex() { + return B16.encode(toBytes()); + } + @Override + public void toBytesSink(BytesSink to) { + to.add(toBytes()); + } + public static class Translator extends TypeTranslator { + @Override + public TransactionType fromParser(BinaryParser parser, Integer hint) { + return fromNumber(parser.readOneInt() << 8 | parser.readOneInt()); + } + + @Override + public TransactionType fromInteger(int integer) { + return fromNumber(integer); + } + + @Override + public TransactionType fromString(String value) { + return TransactionType.valueOf(value); + } + } + + @SuppressWarnings("unused") + public static Translator translate = new Translator(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java b/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java new file mode 100644 index 0000000000..f7efd08ed2 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java @@ -0,0 +1,15 @@ +package com.ripple.core.types.known.generic; + +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; + +public class Validation extends STObject { + public static boolean isValidation(STObject source) { + return source.has(UInt32.LedgerSequence) && + source.has(UInt32.SigningTime) && + source.has(Hash256.LedgerHash) && + source.has(Blob.Signature); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java new file mode 100644 index 0000000000..c5dc3f7f3d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java @@ -0,0 +1,59 @@ +package com.ripple.core.types.known.sle; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.formats.LEFormat; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.entries.AccountRoot; +import com.ripple.core.types.known.sle.entries.DirectoryNode; +import com.ripple.core.types.known.sle.entries.Offer; +import com.ripple.core.types.known.sle.entries.RippleState; + +import java.util.TreeSet; + +public class LedgerEntry extends STObject { + public LedgerEntry(LedgerEntryType type) { + setFormat(LEFormat.formats.get(type)); + put(Field.LedgerEntryType, type); + } + + public LedgerEntryType ledgerEntryType() {return ledgerEntryType(this);} + public Hash256 index() { return get(Hash256.index); } + public UInt32 flags() {return get(UInt32.Flags);} + public Hash256 ledgerIndex() {return get(Hash256.LedgerIndex);} + + public void flags(UInt32 val) {put(Field.Flags, val);} + public void ledgerIndex(Hash256 val) {put(Field.LedgerIndex, val);} + + public boolean hasLedgerIndex() {return has(Hash256.LedgerIndex);} + + public TreeSet owners() { + TreeSet owners = new TreeSet<>(); + + if (has(Field.LowLimit)) { + owners.add(get(Amount.LowLimit).issuer()); + } + if (has(Field.HighLimit)) { + owners.add(get(Amount.HighLimit).issuer()); + } + if (has(Field.Account)) { + owners.add(get(AccountID.Account)); + } + + return owners; + } + + public void index(Hash256 index) { + put(Hash256.index, index); + } + + public void setDefaults() { + if (flags() == null) { + flags(UInt32.ZERO); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java new file mode 100644 index 0000000000..9b9086cd72 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java @@ -0,0 +1,32 @@ +package com.ripple.core.types.known.sle; + +import com.ripple.core.coretypes.Vector256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class LedgerHashes extends LedgerEntry { + public LedgerHashes() { + super(LedgerEntryType.LedgerHashes); + } + + public Vector256 hashes() { + return get(Vector256.Hashes); + } + + public void hashes(Vector256 hashes) { + put(Vector256.Hashes, hashes); + } + + public UInt32 lastLedgerSequence() { + return get(UInt32.LastLedgerSequence); + } + + public UInt32 firstLedgerSequence() {return get(UInt32.FirstLedgerSequence);} + + public void firstLedgerSequence(UInt32 val) { put(UInt32.FirstLedgerSequence, val);} + + public void lastLedgerSequence(UInt32 val) { put(UInt32.LastLedgerSequence, val);} + + public boolean hasFirstLedgerSequence() {return has(UInt32.FirstLedgerSequence);} + public boolean hasLastLedgerSequence() {return has(UInt32.LastLedgerSequence);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java new file mode 100644 index 0000000000..3739109d97 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java @@ -0,0 +1,18 @@ +package com.ripple.core.types.known.sle; + + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; + +// this class has a PreviousTxnID and PreviousTxnLgrSeq +abstract public class ThreadedLedgerEntry extends LedgerEntry { + public ThreadedLedgerEntry(LedgerEntryType type) { + super(type); + } + public UInt32 previousTxnLgrSeq() {return get(UInt32.PreviousTxnLgrSeq);} + public Hash256 previousTxnID() {return get(Hash256.PreviousTxnID);} + public void previousTxnLgrSeq(UInt32 val) {put(Field.PreviousTxnLgrSeq, val);} + public void previousTxnID(Hash256 val) {put(Field.PreviousTxnID, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java new file mode 100644 index 0000000000..22f26def99 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java @@ -0,0 +1,71 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.hash.Hash128; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.enums.LedgerFlag; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.ThreadedLedgerEntry; + +public class AccountRoot extends ThreadedLedgerEntry { + public AccountRoot() { + super(LedgerEntryType.AccountRoot); + } + + public UInt32 sequence() {return get(UInt32.Sequence);} + public UInt32 transferRate() {return get(UInt32.TransferRate);} + public UInt32 walletSize() {return get(UInt32.WalletSize);} + public UInt32 ownerCount() {return get(UInt32.OwnerCount);} + public Hash128 emailHash() {return get(Hash128.EmailHash);} + public Hash256 walletLocator() {return get(Hash256.WalletLocator);} + public Amount balance() {return get(Amount.Balance);} + public Blob messageKey() {return get(Blob.MessageKey);} + public Blob domain() {return get(Blob.Domain);} + public AccountID account() {return get(AccountID.Account);} + public AccountID regularKey() {return get(AccountID.RegularKey);} + + public void sequence(UInt32 val) {put(Field.Sequence, val);} + public void transferRate(UInt32 val) {put(Field.TransferRate, val);} + public void walletSize(UInt32 val) {put(Field.WalletSize, val);} + public void ownerCount(UInt32 val) {put(Field.OwnerCount, val);} + public void emailHash(Hash128 val) {put(Field.EmailHash, val);} + public void walletLocator(Hash256 val) {put(Field.WalletLocator, val);} + public void balance(Amount val) {put(Field.Balance, val);} + public void messageKey(Blob val) {put(Field.MessageKey, val);} + public void domain(Blob val) {put(Field.Domain, val);} + public void account(AccountID val) {put(Field.Account, val);} + public void regularKey(AccountID val) {put(Field.RegularKey, val);} + + public boolean requiresAuth() { + return flags().testBit(LedgerFlag.RequireAuth); + } + + public boolean hasAccountTxnID() {return has(Hash256.AccountTxnID);} + public boolean hasDomain() {return has(Blob.Domain);} + public boolean hasEmailHash() {return has(Hash128.EmailHash);} + public boolean hasMessageKey() {return has(Blob.MessageKey);} + public boolean hasRegularKey() {return has(AccountID.RegularKey);} + public boolean hasTickSize() {return has(UInt8.TickSize);} + public boolean hasTransferRate() {return has(UInt32.TransferRate);} + public boolean hasWalletLocator() {return has(Hash256.WalletLocator);} + public boolean hasWalletSize() {return has(UInt32.WalletSize);} + + public Hash256 accountTxnID() {return get(Hash256.AccountTxnID);} + public UInt8 tickSize() {return get(UInt8.TickSize);} + + public void accountTxnID(Hash256 val) { put(Hash256.AccountTxnID, val);} + public void tickSize(UInt8 val) { put(UInt8.TickSize, val);} + + @Override + public void setDefaults() { + super.setDefaults(); + if (ownerCount() == null) { + ownerCount(new UInt32(0)); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java new file mode 100644 index 0000000000..8b580af8ef --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java @@ -0,0 +1,22 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.STArray; +import com.ripple.core.coretypes.Vector256; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.LedgerEntry; + +public class Amendments extends LedgerEntry { + public Amendments() { + super(LedgerEntryType.Amendments); + } + + public STArray majorities() {return get(STArray.Majorities);} + public Vector256 amendments() {return get(Vector256.Amendments);} + + public void amendments(Vector256 val) { put(Vector256.Amendments, val);} + public void majorities(STArray val) { put(STArray.Majorities, val);} + + public boolean hasAmendments() {return has(Vector256.Amendments);} + public boolean hasMajorities() {return has(STArray.Majorities);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java new file mode 100644 index 0000000000..310232b1dd --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java @@ -0,0 +1,40 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class Check extends IndexedLedgerEntry { + public Check() { + super(LedgerEntryType.Check); + } + + public boolean hasSourceTag() {return has(UInt32.SourceTag);} + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} + + public UInt32 sourceTag() {return get(UInt32.SourceTag);} + public UInt32 sequence() {return get(UInt32.Sequence);} + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + public UInt64 destinationNode() {return get(UInt64.DestinationNode);} + public Hash256 invoiceID() {return get(Hash256.InvoiceID);} + public Amount sendMax() {return get(Amount.SendMax);} + public AccountID account() {return get(AccountID.Account);} + public AccountID destination() {return get(AccountID.Destination);} + + public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} + public void sequence(UInt32 val) { put(UInt32.Sequence, val);} + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + public void destinationNode(UInt64 val) { put(UInt64.DestinationNode, val);} + public void invoiceID(Hash256 val) { put(Hash256.InvoiceID, val);} + public void sendMax(Amount val) { put(Amount.SendMax, val);} + public void destination(AccountID val) { put(AccountID.Destination, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java new file mode 100644 index 0000000000..7f995ecc1c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java @@ -0,0 +1,18 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class DepositPreauthLe extends IndexedLedgerEntry { + public DepositPreauthLe() { + super(LedgerEntryType.DepositPreauth); + } + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + + public AccountID account() {return get(AccountID.Account);} + + public AccountID authorize() {return get(AccountID.Authorize);} + public void authorize(AccountID val) { put(AccountID.Authorize, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java new file mode 100644 index 0000000000..f46a7d7973 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java @@ -0,0 +1,88 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Currency; +import com.ripple.core.coretypes.Vector256; +import com.ripple.core.coretypes.hash.Hash160; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.LedgerEntry; + +public class DirectoryNode extends LedgerEntry { + public DirectoryNode() { + super(LedgerEntryType.DirectoryNode); + } + + public UInt64 indexNext() {return get(UInt64.IndexNext);} + public UInt64 indexPrevious() {return get(UInt64.IndexPrevious);} + public UInt64 exchangeRate() {return get(UInt64.ExchangeRate);} + public Hash256 rootIndex() {return get(Hash256.RootIndex);} + public AccountID owner() {return get(AccountID.Owner);} + public Hash160 takerPaysCurrency() {return get(Hash160.TakerPaysCurrency);} + public Hash160 takerPaysIssuer() {return get(Hash160.TakerPaysIssuer);} + public Hash160 takerGetsCurrency() {return get(Hash160.TakerGetsCurrency);} + public Hash160 takerGetsIssuer() {return get(Hash160.TakerGetsIssuer);} + public Vector256 indexes() {return get(Vector256.Indexes);} + public void indexNext(UInt64 val) {put(Field.IndexNext, val);} + public void indexPrevious(UInt64 val) {put(Field.IndexPrevious, val);} + public void exchangeRate(UInt64 val) {put(Field.ExchangeRate, val);} + public void rootIndex(Hash256 val) {put(Field.RootIndex, val);} + public void owner(AccountID val) {put(Field.Owner, val);} + public void takerPaysCurrency(Hash160 val) {put(Field.TakerPaysCurrency, val);} + public void takerPaysIssuer(Hash160 val) {put(Field.TakerPaysIssuer, val);} + public void takerGetsCurrency(Hash160 val) {put(Field.TakerGetsCurrency, val);} + public void takerGetsIssuer(Hash160 val) {put(Field.TakerGetsIssuer, val);} + public void indexes(Vector256 val) {put(Field.Indexes, val);} + + public boolean hasIndexNext() {return has(UInt64.IndexNext);} + public boolean hasIndexPrevious() {return has(UInt64.IndexPrevious);} + public boolean hasExchangeRate() {return has(UInt64.ExchangeRate);} + public boolean hasOwner() {return has(AccountID.Owner);} + public boolean hasTakerPaysCurrency() {return has(Hash160.TakerPaysCurrency);} + public boolean hasTakerPaysIssuer() {return has(Hash160.TakerPaysIssuer);} + public boolean hasTakerGetsCurrency() {return has(Hash160.TakerGetsCurrency);} + public boolean hasTakerGetsIssuer() {return has(Hash160.TakerGetsIssuer);} + + public Hash256 nextIndex() { + return Index.directoryNode(rootIndex(), indexNext()); + } + public Hash256 prevIndex() { + return Index.directoryNode(rootIndex(), indexPrevious()); + } + + public boolean hasPreviousIndex() { + return hasIndexPrevious() && !indexPrevious().isZero(); + } + + public boolean hasNextIndex() { + return hasIndexNext() && !indexNext().isZero(); + } + + public boolean isRootIndex() { + return rootIndex().equals(index()); + } + + public void setExchangeDefaults() { + if (takerGetsCurrency() == null) { + takerGetsCurrency(Currency.XRP); + takerGetsIssuer(AccountID.XRP_ISSUER); + } else if (takerPaysCurrency() == null) { + takerPaysCurrency(Currency.XRP); + takerPaysIssuer(AccountID.XRP_ISSUER); + } + } + + @Override + public void setDefaults() { + super.setDefaults(); + if (exchangeRate() != null) { + setExchangeDefaults(); + } + if (indexes() == null) { + indexes(new Vector256()); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java new file mode 100644 index 0000000000..ff822c6757 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java @@ -0,0 +1,74 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.tx.Transaction; + +import java.util.ArrayList; + +public class Escrow extends IndexedLedgerEntry { + public Escrow() { + super(LedgerEntryType.Escrow); + } + + @Override + public void setDefaults() { + super.setDefaults(); + if (multiParty()) { + if (!has(UInt64.DestinationNode)) { + put(UInt64.DestinationNode, UInt64.ZERO); + } + } + } + + @Override + public ArrayList ownerDirectoryIndexes(Transaction nullableContext) { + ArrayList indexes = super.ownerDirectoryIndexes(nullableContext); + if (multiParty()) { + Hash256 destinationOwnerDir = + Index.ownerDirectory(destination()); + indexes.add(Index.directoryNode( + destinationOwnerDir, destinationNode())); + } + return indexes; + } + + private boolean multiParty() { + return !get(AccountID.Account).equals(destination()); + } + + public AccountID account() {return get(AccountID.Account);} + public AccountID destination() {return get(AccountID.Destination);} + public Amount amount() {return get(Amount.Amount);} + public Blob condition() {return get(Blob.Condition);} + public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public UInt32 finishAfter() {return get(UInt32.FinishAfter);} + public UInt32 sourceTag() {return get(UInt32.SourceTag);} + public UInt64 destinationNode() {return get(UInt64.DestinationNode);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + + public void amount(Amount val) { put(Amount.Amount, val);} + public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} + public void condition(Blob val) { put(Blob.Condition, val);} + public void destination(AccountID val) { put(AccountID.Destination, val);} + public void destinationNode(UInt64 val) { put(UInt64.DestinationNode, val);} + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void finishAfter(UInt32 val) { put(UInt32.FinishAfter, val);} + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} + + public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} + public boolean hasCondition() {return has(Blob.Condition);} + public boolean hasDestinationNode() {return has(UInt64.DestinationNode);} + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasFinishAfter() {return has(UInt32.FinishAfter);} + public boolean hasSourceTag() {return has(UInt32.SourceTag);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java new file mode 100644 index 0000000000..ce8fca505d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java @@ -0,0 +1,22 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.LedgerEntry; + +public class FeeSettings extends LedgerEntry { + public FeeSettings() { + super(LedgerEntryType.Amendments); + } + public UInt32 referenceFeeUnits() {return get(UInt32.ReferenceFeeUnits);} + public UInt32 reserveBase() {return get(UInt32.ReserveBase);} + public UInt32 reserveIncrement() {return get(UInt32.ReserveIncrement);} + public UInt64 baseFee() {return get(UInt64.BaseFee);} + + public void baseFee(UInt64 val) { put(UInt64.BaseFee, val);} + public void referenceFeeUnits(UInt32 val) { put(UInt32.ReferenceFeeUnits, val);} + public void reserveBase(UInt32 val) { put(UInt32.ReserveBase, val);} + public void reserveIncrement(UInt32 val) { put(UInt32.ReserveIncrement, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java new file mode 100644 index 0000000000..93c15e2f80 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java @@ -0,0 +1,12 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.types.known.tx.Transaction; + +import java.util.ArrayList; + +public interface IHasOwners { + ArrayList ownerDirectoryIndexes(Transaction nullableContext); + AccountID account(Transaction nullableContext); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java new file mode 100644 index 0000000000..37ff656961 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java @@ -0,0 +1,56 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.ThreadedLedgerEntry; +import com.ripple.core.types.known.tx.Transaction; + +import java.util.ArrayList; + +public abstract class IndexedLedgerEntry extends ThreadedLedgerEntry implements IHasOwners { + public IndexedLedgerEntry(LedgerEntryType type) { + super(type); + } + + @Override + public void setDefaults() { + super.setDefaults(); + if (!has(Field.OwnerNode)) { + put(UInt64.OwnerNode, UInt64.ZERO); + } + } + + @Override + public AccountID account(Transaction nullableContext) { + AccountID account = account(); + if (account == null) { + if (nullableContext != null) { + account = nullableContext.account(); + } else { + throw new IllegalStateException("Cant determine account for: " + prettyJSON()); + } + } + return account; + } + + @Override + public ArrayList ownerDirectoryIndexes(Transaction nullableContext) { + Hash256 ownerDir = Index.ownerDirectory(account(nullableContext)); + ArrayList indexes = new ArrayList<>(); + indexes.add(Index.directoryNode(ownerDir, ownerNode())); + return indexes; + } + + private UInt64 ownerNode() { + return get(UInt64.OwnerNode); + } + + private AccountID account() { + return get(AccountID.Account); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java new file mode 100644 index 0000000000..ceaa7a6732 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java @@ -0,0 +1,219 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.*; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.ThreadedLedgerEntry; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; + +public class Offer extends ThreadedLedgerEntry { + public Offer() { + super(LedgerEntryType.Offer); + } + + /** + * Use the BookDirectory field + * + * @return how much must `pay` to `get` one. + * + */ + public BigDecimal directoryAskQuality() { + return Quality.fromBookDirectory(bookDirectory(), + takerPays().isNative(), + takerGets().isNative()); + } + + /** + * @return how much must `pay` to `get` one. + */ + public BigDecimal askQuality() { + return takerPays().computeQuality(takerGets()); + } + + /** + * @return how much `get` if `pay` one. + */ + public BigDecimal bidQuality() { + return takerGets().computeQuality(takerPays()); + } + + /** + * + * @return One of TakerGets issue, eg 1/USD/BITSTAMP or 1/EUR/SNAPSWAP + */ + public Amount getsOne() { + return takerGets().one(); + } + /** + * + * @return One of TakerPays issue, eg 1/USD/BITSTAMP or 1/EUR/SNAPSWAP + */ + public Amount paysOne() { + return takerPays().one(); + } + + public String getPayCurrencyPair() { + return takerGets().currencyString() + "/" + + takerPays().currencyString(); + } + + // TODO: create an OfferExecution object for this + public STObject executed(STObject finalFields) { + // where `this` is an AffectedNode nodeAsPrevious + STObject executed = new STObject(); + executed.put(Amount.TakerPays, finalFields.get(Amount.TakerPays).subtract(takerPays())); + executed.put(Amount.TakerGets, finalFields.get(Amount.TakerGets).subtract(takerGets())); + return executed; + } + + public Hash256 lineIndex(Amount amt) { + return account().lineIndex(amt.issue()); + } + + public Hash256 fundingSource() { + Amount takerGets = takerGets(); + if (account().equals(takerGets.issuer())) { + return null; + } + else if (takerGets.isNative()) { + return Index.accountRoot(account()); + } else { + return lineIndex(takerGets); + } + } + + public Vector256 lineIndexes() { + Vector256 ret = new Vector256(); + + Amount takerGets = takerGets(); + for (Amount amt : new Amount[]{takerGets, takerPays()}) { + + // Actually want to compare by reference here :) + if (amt == takerGets()) { + // selling own funds + continue; + } + if (!amt.isNative()) { + ret.add(lineIndex(amt)); + } + } + return ret; + } + + public Hash256 bookBase() { + return Index.bookStart(takerPays().issue(), takerGets().issue()); + } + + public boolean belongsToBook(Hash256 bookBase) { + byte[] baseBytes = bookBase.bytes(); + byte[] directoryBytes = bookDirectory().bytes(); + + for (int i = 0; i < 24; i++) { + if (baseBytes[i] != directoryBytes[i]) { + return false; + } + } + return true; + } + + public boolean sellingOwnFunds() { + return account().equals(takerGets().issuer()); + } + + public Amount takerGetsFunded() { + return has(Field.taker_gets_funded) ? get(Amount.taker_gets_funded) : takerGets(); + } + public Amount takerPaysFunded() { + return has(Field.taker_pays_funded) ? get(Amount.taker_pays_funded) : takerPays(); + } + + public static Comparator qualityAscending = Comparator.comparing(Offer::directoryAskQuality); + + public static Iterator iterateCollection(Collection offers) { + final Iterator iterator = offers.iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Offer next() { + return (Offer) iterator.next(); + } + + @Override + public void remove() { + iterator.remove(); + + } + }; + } + + public Hash256 bookNodeDirectoryIndex() { + return Index.directoryNode(bookDirectory(), bookNode()); + } + + public Hash256 ownerNodeDirectoryIndex() { + Hash256 ownerDir = Index.ownerDirectory(account()); + return Index.directoryNode(ownerDir, ownerNode()); + } + + + public UInt32 sequence() {return get(UInt32.Sequence);} + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt64 bookNode() {return get(UInt64.BookNode);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + public Hash256 bookDirectory() {return get(Hash256.BookDirectory);} + public Amount takerPays() {return get(Amount.TakerPays);} + public Amount takerGets() {return get(Amount.TakerGets);} + public AccountID account() {return get(AccountID.Account);} + public void sequence(UInt32 val) {put(Field.Sequence, val);} + public void expiration(UInt32 val) {put(Field.Expiration, val);} + public void bookNode(UInt64 val) {put(Field.BookNode, val);} + public void ownerNode(UInt64 val) {put(Field.OwnerNode, val);} + public void bookDirectory(Hash256 val) {put(Field.BookDirectory, val);} + public void takerPays(Amount val) {put(Field.TakerPays, val);} + public void takerGets(Amount val) {put(Field.TakerGets, val);} + public void account(AccountID val) {put(Field.Account, val);} + + public boolean hasExpiration() {return has(UInt32.Expiration);} + + public Hash256[] directoryIndexes() { + return new Hash256[]{bookNodeDirectoryIndex(), ownerNodeDirectoryIndex()}; + } + + @Override + public void setDefaults() { + super.setDefaults(); + setOfferDefaults(); + } + + public void setOfferDefaults() { + if (bookNode() == null) { + bookNode(UInt64.ZERO); + } + if (ownerNode() == null) { + ownerNode(UInt64.ZERO); + } + } + + public IssuePair issuePair() { + return new IssuePair(takerPays().issue(), takerGets().issue()); + } + + public Amount payToGet(Amount funded) { + BigDecimal quality = directoryAskQuality(); + // Multiply by one as that will do the rounding operation we want + return paysOne().multiply(funded.multiply(quality)); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java new file mode 100644 index 0000000000..fddb7126fd --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java @@ -0,0 +1,20 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.Issue; +import com.ripple.core.coretypes.IssuePair; + +public class OfferDirectory extends DirectoryNode { + public IssuePair issuePair() { + return new IssuePair(takerPaysIssue(), takerGetsIssue()); + } + + public Issue takerGetsIssue() { + // TODO: remove wrapper + return Issue.from160s(takerGetsCurrency(), takerGetsIssuer()); + } + public Issue takerPaysIssue() { + // TODO: remove wrapper + return Issue.from160s(takerPaysCurrency(), takerPaysIssuer()); + } + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java new file mode 100644 index 0000000000..b6f784e4b8 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java @@ -0,0 +1,3 @@ +package com.ripple.core.types.known.sle.entries; + +public class OwnerDirectory extends DirectoryNode { } diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java new file mode 100644 index 0000000000..97a2786b2a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java @@ -0,0 +1,42 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class PayChannel extends IndexedLedgerEntry { + public PayChannel() { + super(LedgerEntryType.PayChannel); + } + + public AccountID account() {return get(AccountID.Account);} + public AccountID destination() {return get(AccountID.Destination);} + public Amount amount() {return get(Amount.Amount);} + public Amount balance() {return get(Amount.Balance);} + public Blob publicKey() {return get(Blob.PublicKey);} + public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt32 settleDelay() {return get(UInt32.SettleDelay);} + public UInt32 sourceTag() {return get(UInt32.SourceTag);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + + public void amount(Amount val) { put(Amount.Amount, val);} + public void balance(Amount val) { put(Amount.Balance, val);} + public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} + public void destination(AccountID val) { put(AccountID.Destination, val);} + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + public void publicKey(Blob val) { put(Blob.PublicKey, val);} + public void settleDelay(UInt32 val) { put(UInt32.SettleDelay, val);} + public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} + + public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasSourceTag() {return has(UInt32.SourceTag);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java new file mode 100644 index 0000000000..02f9f2ad2e --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java @@ -0,0 +1,224 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Currency; +import com.ripple.core.coretypes.Issue; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.enums.LedgerFlag; +import com.ripple.core.fields.AmountField; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.ThreadedLedgerEntry; + +import java.util.Arrays; +import java.util.List; + +public class RippleState extends ThreadedLedgerEntry { + /** + The RippleState is a ledger entry which roughly speaking defines the balance and + trust limits between two accounts. + + Like all current ledger entries, it has a canonical form for hashing that + doesn't necessarily communicate the information in a way that is clear or + obvious to a human. The current json format for some ledger entries is very + close to the hashing format, and isn't any better. + + The two accounts on the link are categorized into a low account, and a high + account by comparing the 160bits of their account id as a big endian unsigned + integer. + + There is one and only one `Balance` stored, using an amount struct with a + neutral `issuer`. ( A uint160 with the numerical value of `1` was chosen as a + placeholder, as the canonical way to represent a null account ) + + The Balance can be negative, zero, or positive and is in terms of the Low + account, such that when it's positive, it defines how much credit the High + account has issued. + + Between any account, there can be two types of balance changes, issuance and + redemption. A redemption is the transferal of previously issued IOUs back to the + owner. + + This implies that for any account, that can they can make a transferal using + funds from two distinct balances. After making this distinction it becomes + nonsensical to say that an account holds negative IOUs from the opposite line. + + Thus, the one Balance in a ripple state actually implies 4 distinct balances. + + ``` + { + ... + "Balance" : { + "currency" : "USD", + "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value" : "100" + }, + "HighLimit" : { + "currency" : "USD", + "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK", + "value" : "500" + }, + "LowLimit" : { + "currency" : "USD", + "issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "value" : "500" + }, + } + ``` + + lowAccount = LowLimit.issuer + hiAccount = HighLimit.issuer + + Balances: + lowAccount has 100/USD/highAccount + lowAccount has 0/USD/lowAccount on the line + + highAccount has 0/USD/lowAccount + highAccount has -100/USD/highAccount on the line + + + * */ + + public RippleState() { + super(LedgerEntryType.RippleState); + } + + public UInt32 highQualityIn() {return get(UInt32.HighQualityIn);} + public UInt32 highQualityOut() {return get(UInt32.HighQualityOut);} + public UInt32 lowQualityIn() {return get(UInt32.LowQualityIn);} + public UInt32 lowQualityOut() {return get(UInt32.LowQualityOut);} + public UInt64 lowNode() {return get(UInt64.LowNode);} + public UInt64 highNode() {return get(UInt64.HighNode);} + public Amount balance() {return get(Amount.Balance);} + public Amount lowLimit() {return get(Amount.LowLimit);} + public Amount highLimit() {return get(Amount.HighLimit);} + public void highQualityIn(UInt32 val) {put(Field.HighQualityIn, val);} + public void highQualityOut(UInt32 val) {put(Field.HighQualityOut, val);} + public void lowQualityIn(UInt32 val) {put(Field.LowQualityIn, val);} + public void lowQualityOut(UInt32 val) {put(Field.LowQualityOut, val);} + public void lowNode(UInt64 val) {put(Field.LowNode, val);} + public void highNode(UInt64 val) {put(Field.HighNode, val);} + public void balance(Amount val) {put(Field.Balance, val);} + public void lowLimit(Amount val) {put(Field.LowLimit, val);} + public void highLimit(Amount val) {put(Field.HighLimit, val);} + + public boolean hasHighQualityIn() {return has(UInt32.HighQualityIn);} + public boolean hasHighQualityOut() {return has(UInt32.HighQualityOut);} + public boolean hasLowQualityIn() {return has(UInt32.LowQualityIn);} + public boolean hasLowQualityOut() {return has(UInt32.LowQualityOut);} + public boolean hasLowNode() {return has(UInt64.LowNode);} + public boolean hasHighNode() {return has(UInt64.HighNode);} + + public AccountID lowAccount() { + return lowLimit().issuer(); + } + + public AccountID highAccount() { + return highLimit().issuer(); + } + + public List sortedAccounts() { + return Arrays.asList(lowAccount(), highAccount()); + } + + public AmountField limitFieldFor(AccountID source) { + if (lowAccount().equals(source)) { + return Amount.LowLimit; + } + if (highAccount().equals(source)) { + return Amount.HighLimit; + } else { + return null; + } + } + + public boolean isFor(AccountID source) { + return lowAccount().equals(source) || highAccount().equals(source); + } + + public boolean isFor(Issue issue) { + return isFor(issue.issuer()) && balance().currency().equals(issue.currency()); + } + + // TODO, can optimize this + public boolean isFor(AccountID s1, AccountID s2, Currency currency) { + return currency.equals(balance().currency()) && isFor(s1) && isFor(s2); + } + + public Currency currency() { + return balance().currency(); + } + + private Amount issuedBy(boolean hi) { + Amount balance; + + if (hi) { + balance = balance().newIssuer(highAccount()); + } else { + balance = balance().negate().newIssuer(lowAccount()); + } + + if (!balance.isPositive()) { + balance = balance.issue().amount(0); + } + return balance; + } + + public Amount issuedByHigh() { + return issuedBy(true); + } + public Amount issuedByLow() { + return issuedBy(false); + } + + public Amount issuedTo(AccountID accountID) { + return issuedBy(isLowAccount(accountID)); + } + + @Deprecated() // "not deprecated but needs fixing" + public boolean authorizedBy(AccountID account) { + UInt32 flags = flags(); + return flags == null || flags.testBit(isHighAccount(account) ? LedgerFlag.HighAuth : LedgerFlag.LowAuth); + } + + private boolean isBitSet(int flags, int flag) { + return (flags & flag) != 0; + } + + private boolean isHighAccount(AccountID account) { + return highAccount().equals(account); + } + private boolean isLowAccount(AccountID account) { + return lowAccount().equals(account); + } + + + public Hash256 lowNodeOwnerDirectory() { + Hash256 ownerDir = Index.ownerDirectory(lowAccount()); + return Index.directoryNode(ownerDir, lowNode()); + } + public Hash256 highNodeOwnerDirectory() { + Hash256 ownerDir = Index.ownerDirectory(highAccount()); + return Index.directoryNode(ownerDir, highNode()); + } + + public Hash256[] directoryIndexes() { + return new Hash256[]{lowNodeOwnerDirectory(), highNodeOwnerDirectory()}; + } + + @Override + public void setDefaults() { + super.setDefaults(); + + if (lowNode() == null) { + lowNode(UInt64.ZERO); + } + if (highNode() == null) { + highNode(UInt64.ZERO); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java new file mode 100644 index 0000000000..68af847605 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java @@ -0,0 +1,32 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.STArray; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class SignerList extends IndexedLedgerEntry { + public SignerList() { + super(LedgerEntryType.SignerList); + } + + @Override + public void setDefaults() { + super.setDefaults(); + if (!has(Field.SignerListID)) { + put(UInt32.SignerListID, UInt32.ZERO); + } + } + + public STArray signerEntries() {return get(STArray.SignerEntries);} + public UInt32 signerListID() {return get(UInt32.SignerListID);} + public UInt32 signerQuorum() {return get(UInt32.SignerQuorum);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + public void signerEntries(STArray val) { put(STArray.SignerEntries, val);} + public void signerListID(UInt32 val) { put(UInt32.SignerListID, val);} + public void signerQuorum(UInt32 val) { put(UInt32.SignerQuorum, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java new file mode 100644 index 0000000000..5d48e3f462 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java @@ -0,0 +1,27 @@ +package com.ripple.core.types.known.sle.entries; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.LedgerEntryType; + +public class Ticket extends IndexedLedgerEntry { + public Ticket() { + super(LedgerEntryType.Ticket); + } + + public AccountID account() {return get(AccountID.Account);} + public AccountID target() {return get(AccountID.Target);} + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt32 sequence() {return get(UInt32.Sequence);} + public UInt64 ownerNode() {return get(UInt64.OwnerNode);} + + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} + public void sequence(UInt32 val) { put(UInt32.Sequence, val);} + public void target(AccountID val) { put(AccountID.Target, val);} + + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasTarget() {return has(AccountID.Target);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java new file mode 100644 index 0000000000..8f174968aa --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java @@ -0,0 +1,116 @@ +package com.ripple.core.types.known.tx; + +import com.ripple.core.coretypes.*; +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.uint.UInt16; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.enums.TransactionFlag; +import com.ripple.core.fields.Field; +import com.ripple.core.formats.TxFormat; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.signed.SignedTransaction; +import com.ripple.crypto.keys.IVerifyingKey; +import com.ripple.utils.HashUtils; + +public class Transaction extends STObject { + public static final boolean CANONICAL_FLAG_DEPLOYED = true; + public static final UInt32 CANONICAL_SIGNATURE = new UInt32(TransactionFlag.FullyCanonicalSig); + + public Transaction(TransactionType type) { + setFormat(TxFormat.formats.get(type)); + put(Field.TransactionType, type); + } + + public SignedTransaction prepare(byte[] pubKeyBytes) { + SignedTransaction tx = SignedTransaction.fromTx(this); + tx.prepare(pubKeyBytes); + return tx; + } + + public TransactionType transactionType() { + return transactionType(this); + } + + public Hash256 signingHash() { + return signingHash(HashPrefix.txSign); + } + + public byte[] signingData() { + return signingData(HashPrefix.txSign); + } + + public boolean verifySignature(AccountID key) { + Blob pubKey = signingPubKey(); + return IVerifyingKey.from(pubKey.toBytes()) + .verify(signingData(), + txnSignature().toBytes()) && + signingKey().equals(key); + } + + public boolean verifyMasterKeySignature() { + return verifySignature(account()); + } + + public void setCanonicalSignatureFlag() { + UInt32 flags = get(UInt32.Flags); + if (flags == null) { + flags = CANONICAL_SIGNATURE; + } else { + flags = flags.or(CANONICAL_SIGNATURE); + } + put(UInt32.Flags, flags); + } + + public UInt32 flags() {return get(UInt32.Flags);} + public UInt32 sourceTag() {return get(UInt32.SourceTag);} + public UInt32 sequence() {return get(UInt32.Sequence);} + public UInt32 lastLedgerSequence() {return get(UInt32.LastLedgerSequence);} + public UInt32 operationLimit() {return get(UInt32.OperationLimit);} + public Hash256 previousTxnID() {return get(Hash256.PreviousTxnID);} + public Hash256 accountTxnID() {return get(Hash256.AccountTxnID);} + public Amount fee() {return get(Amount.Fee);} + public Blob signingPubKey() {return get(Blob.SigningPubKey);} + public Blob txnSignature() {return get(Blob.TxnSignature);} + public AccountID account() {return get(AccountID.Account);} + + public void transactionType(UInt16 val) {put(Field.TransactionType, val);} + public void flags(UInt32 val) {put(Field.Flags, val);} + public void sourceTag(UInt32 val) {put(Field.SourceTag, val);} + public void sequence(UInt32 val) {put(Field.Sequence, val);} + public void lastLedgerSequence(UInt32 val) {put(Field.LastLedgerSequence, val);} + public void operationLimit(UInt32 val) {put(Field.OperationLimit, val);} + public void previousTxnID(Hash256 val) {put(Field.PreviousTxnID, val);} + public void accountTxnID(Hash256 val) {put(Field.AccountTxnID, val);} + public void fee(Amount val) {put(Field.Fee, val);} + public void signingPubKey(Blob val) {put(Field.SigningPubKey, val);} + public void txnSignature(Blob val) {put(Field.TxnSignature, val);} + public void account(AccountID val) {put(Field.Account, val);} + + public boolean hasFlags() {return has(UInt32.Flags);} + public boolean hasSourceTag() {return has(UInt32.SourceTag);} + public boolean hasLastLedgerSequence() {return has(UInt32.LastLedgerSequence);} + public boolean hasOperationLimit() {return has(UInt32.OperationLimit);} + public boolean hasPreviousTxnID() {return has(Hash256.PreviousTxnID);} + public boolean hasAccountTxnID() {return has(Hash256.AccountTxnID);} + public boolean hasTxnSignature() {return has(Blob.TxnSignature);} + public boolean hasSigners() {return has(STArray.Signers);} + public boolean hasMemos() {return has(STArray.Memos);} + + public Hash256 hash() { + return get(Hash256.hash); + } + + public Hash256 createHash() { + HalfSha512 id = HalfSha512.prefixed256(HashPrefix.transactionID); + toBytesSink(id); + return id.finish(); + } + + public AccountID signingKey() { + // May be a regular Key + byte[] pubKey = HashUtils.SHA256_RIPEMD160(signingPubKey().toBytes()); + return AccountID.fromBytes(pubKey); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java new file mode 100644 index 0000000000..9c399b73a0 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java @@ -0,0 +1,156 @@ +package com.ripple.core.types.known.tx.result; + +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt16; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.SerializedType; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.LedgerEntry; + +// TODO: fix up this nonsense +public class AffectedNode extends STObject { + public final Field field; + public final STObject nested; + + public AffectedNode(STObject source) { + fields = source.getFields(); + field = getField(); + nested = nestedObject(); + } + + public boolean isOffer() { + return ledgerEntryType() == LedgerEntryType.Offer; + } + + public boolean isAccountRoot() { + return ledgerEntryType() == LedgerEntryType.AccountRoot; + } + + public boolean isRippleState() { + return ledgerEntryType() == LedgerEntryType.RippleState; + } + + public boolean isDirectoryNode() { + return ledgerEntryType() == LedgerEntryType.DirectoryNode; + } + + public boolean wasPreviousNode() { + return isDeletedNode() || isModifiedNode(); + } + + public boolean isFinalNode() { + return true; + } + + public boolean isCreatedNode() { + return field == Field.CreatedNode; + } + + public boolean isDeletedNode() { + return field == Field.DeletedNode; + } + + public boolean isModifiedNode() { + return field == Field.ModifiedNode; + } + + public Field getField() { +// return iterator().next(); + return fields.firstKey(); + } + + public Hash256 ledgerIndex() { + return nested.get(Hash256.LedgerIndex); + } + + public LedgerEntryType ledgerEntryType() { + return ledgerEntryType(nested); + } + + private STObject nestedObject() { + return (STObject) get(getField()); + } + + /** + * @return - LedgerEntry before the transaction (or after in the case of + * a CreatedNode) + */ + public LedgerEntry nodeAsPrevious() { + return (LedgerEntry) rebuildFromMeta(true); + } + + public LedgerEntry nodeAsFinal() { + return (LedgerEntry) rebuildFromMeta(false); + } + + private STObject rebuildFromMeta(boolean asPrevious) { + boolean created = isCreatedNode(); + STObject mixed = new STObject(); + + // The first object has only a single key + Field wrapperField = created ? Field.CreatedNode : + isDeletedNode() ? Field.DeletedNode : + Field.ModifiedNode; + + STObject wrapped = (STObject) get(wrapperField); + + Field finalFields = created ? Field.NewFields : + Field.FinalFields; + + // You may get some AccountRoot objects like this + if (!wrapped.has(finalFields)) { + STObject source = new STObject(wrapped.getFields()); + source.put(Hash256.index, wrapped.get(Hash256.LedgerIndex)); + source.remove(Field.LedgerIndex); + return STObject.formatted(source); + } + + // Get all the final fields + STObject finals = (STObject) wrapped.get(finalFields); + for (Field field : finals) { + mixed.put(field, finals.get(field)); + } + + // Then layer over the previous fields if desired as previous + // DirectoryNode LedgerEntryType won't have `PreviousFields` + if (asPrevious && wrapped.has(Field.PreviousFields)) { + STObject previous = wrapped.get(STObject.PreviousFields); + for (Field field : previous) { + mixed.put(field, previous.get(field)); + } + } + + // Keep the inner most fields + for (Field field : wrapped) { + switch (field) { + case NewFields: + case PreviousFields: + case FinalFields: + continue; + default: + SerializedType value = wrapped.get(field); + if (field == Field.LedgerIndex) { + field = Field.index; + } + mixed.put(field, value); + + } + } + return STObject.formatted(mixed); + } + + public static boolean isAffectedNode(STObject source) { + return (source.size() == 1 && ( + source.has(DeletedNode) || + source.has(CreatedNode) || + source.has(ModifiedNode))); + } + + public boolean removedField(Field field) { + return nested.has(Field.PreviousFields) && + nested.get(STObject.PreviousFields).has(field) && + nested.has(Field.FinalFields) && + !nested.get(STObject.FinalFields).has(field); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java new file mode 100644 index 0000000000..c25183436a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java @@ -0,0 +1,50 @@ +package com.ripple.core.types.known.tx.result; + +import com.ripple.core.coretypes.STArray; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.serialized.enums.EngineResult; +import com.ripple.core.types.known.sle.LedgerEntry; + +import java.util.Iterator; + +public class TransactionMeta extends STObject { + public static boolean isTransactionMeta(STObject source) { + return source.has(UInt8.TransactionResult) && + source.has(STArray.AffectedNodes); + } + + public EngineResult engineResult() { + return engineResult(this); + } + + public Iterable affectedNodes() { + STArray nodes = get(STArray.AffectedNodes); + final Iterator iterator = nodes.iterator(); + return () -> iterateAffectedNodes(iterator); + } + + private static Iterator iterateAffectedNodes(final Iterator iterator) { + return new Iterator() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public AffectedNode next() { + return (AffectedNode) iterator.next(); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } + + public UInt32 transactionIndex() { + return get(UInt32.TransactionIndex); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java new file mode 100644 index 0000000000..2e4467bf14 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java @@ -0,0 +1,299 @@ +package com.ripple.core.types.known.tx.result; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.STArray; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.EngineResult; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.sle.entries.AccountRoot; +import com.ripple.core.types.known.tx.Transaction; +import com.ripple.encodings.common.B16; +import org.json.JSONObject; + +import java.util.Map; +import java.util.TreeMap; + +public class TransactionResult implements Comparable { + // The json formatting of transaction results is a MESS + public enum Source { + request_tx_result, + request_account_tx, + request_account_tx_binary, + request_tx_binary, + ledger_transactions_expanded_with_ledger_index_injected, + transaction_subscription_notification + } + + public EngineResult engineResult; + public UInt32 ledgerIndex; + public Hash256 hash; + + // TODO: in practice this class is GENERALLY only for validated results. + // NOT strictly true as you can get results from closed but not validated + // ledgers! Though you would want to beyond testing ... + public boolean validated; + + public TransactionResult(long ledgerIndex, Hash256 hash, Transaction txn, TransactionMeta meta) { + this.ledgerIndex = new UInt32(ledgerIndex); + this.hash = hash; + this.txn = txn; + this.meta = meta; + this.engineResult = meta.engineResult(); + this.validated = true; + } + + public Transaction txn; + public TransactionMeta meta; + + public TransactionType transactionType() { + return txn.transactionType(); + } + + public AccountID createdAccount() { + AccountID destination = null; + Hash256 destinationIndex = null; + + if (transactionType() == TransactionType.Payment && meta.has(Field.AffectedNodes)) { + STArray affected = meta.get(STArray.AffectedNodes); + for (STObject node : affected) { + if (node.has(STObject.CreatedNode)) { + STObject created = node.get(STObject.CreatedNode); + if (STObject.ledgerEntryType(created) == LedgerEntryType.AccountRoot) { + if (destination == null) { + destination = txn.get(AccountID.Destination); + destinationIndex = Index.accountRoot(destination); + } + if (destinationIndex.equals(created.get(Hash256.LedgerIndex))) { + return destination; + } + } + } + } + } + return null; + } + + public Map modifiedRoots() { + TreeMap accounts = null; + + if (meta.has(Field.AffectedNodes)) { + accounts = new TreeMap<>(); + for (AffectedNode fields : meta.affectedNodes()) { + if (fields.isModifiedNode() && fields.isAccountRoot()) { + AccountRoot root = (AccountRoot) fields.nodeAsFinal(); + //noinspection StatementWithEmptyBody + if (root.account() != null) { + accounts.put(root.account(), root); + } else { + // TODO: Remember why these modified nodes have no + // FinalFields or NewFields + /* + {"ModifiedNode": { + "LedgerIndex": "2C6F7594FB7471F4983C2BC691AAC2F25F8DB88D455985B4181E053D7AB23006", + "PreviousTxnLgrSeq": 35561097, + "LedgerEntryType": "AccountRoot", + "index": "2C6F7594FB7471F4983C2BC691AAC2F25F8DB88D455985B4181E053D7AB23006", + "PreviousTxnID": "67EE84E892FBEDF5FD52D511FF1E833870A2B8104CA5FF9BA89867A528A5D3ED" + }} + * */ + } + } + } + } + return accounts; + } + + public AccountID initiatingAccount() { + return txn.get(AccountID.Account); + } + + public int compareTo(TransactionResult o2) { + TransactionResult o1 = this; + int i = o1.ledgerIndex.compareTo(o2.ledgerIndex); + if (i != 0) { + return i; + } else { + return o1.meta.transactionIndex() + .compareTo(o2.meta.transactionIndex()); + } + } + + public static TransactionResult fromJSON(ObjectNode json) { + // TODO: obviously ... + return fromJSON(new JSONObject(json.toString())); + } + + public static TransactionResult fromJSON(JSONObject json) { + boolean binary; + + String metaKey = json.has("meta") ? "meta" : "metaData"; + + String txKey = json.has("transaction") ? "transaction" : + json.has("tx") ? "tx" : + json.has("tx_blob") ? "tx_blob" : null; + + if (txKey == null && !json.has("TransactionType")) { + throw new IllegalArgumentException("This json isn't a transaction " + json); + } + + binary = txKey != null && json.get(txKey) instanceof String; + + Transaction txn; + if (txKey == null) { + // This should parse the `hash` field + txn = (Transaction) STObject.fromJSONObject(json); + } else { + txn = (Transaction) parseObject(json, txKey, binary); + if (json.has("hash")) { + txn.put(Hash256.hash, Hash256.fromHex(json.getString("hash"))); + } else if (binary) { + byte[] decode = B16.decode(json.getString(txKey)); + txn.put(Hash256.hash, Index.transactionID(decode)); + } + } + + TransactionMeta meta = (TransactionMeta) parseObject(json, metaKey, binary); + long ledger_index = json.optLong("ledger_index", 0); + if (ledger_index == 0 && !binary) { + ledger_index = json.getJSONObject(txKey).getLong("ledger_index"); + } + + TransactionResult tr = new TransactionResult(ledger_index, txn.get(Hash256.hash), txn, meta); +// if (json.has("ledger_hash")) { +// tr.ledgerHash = Hash256.fromHex(json.getString("ledger_hash")); +// } + return tr; + } + + private static STObject parseObject(JSONObject json, String key, boolean binary) { + if (binary) { + return STObject.fromHex(json.getString(key)); + } else { + JSONObject tx_json = json.getJSONObject(key); + return STObject.fromJSONObject(tx_json); + } + } + + public TransactionResult(JSONObject json, Source resultMessageSource) { + if (resultMessageSource == Source.transaction_subscription_notification) { + + engineResult = EngineResult.valueOf(json.getString("engine_result")); + validated = json.getBoolean("validated"); +// ledgerHash = Hash256.fromHex(json.getString("ledger_hash")); + ledgerIndex = new UInt32(json.getLong("ledger_index")); + + if (json.has("transaction")) { + txn = (Transaction) STObject.fromJSONObject(json.getJSONObject("transaction")); + hash = txn.get(Hash256.hash); + } + + if (json.has("meta")) { + meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); + } + } + else if (resultMessageSource == Source.ledger_transactions_expanded_with_ledger_index_injected) { + validated = true; + meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("metaData")); + txn = (Transaction) STObject.fromJSONObject(json); + hash = txn.get(Hash256.hash); + engineResult = meta.engineResult(); + ledgerIndex = new UInt32(json.getLong("ledger_index")); + + } else if (resultMessageSource == Source.request_tx_result) { + validated = json.optBoolean("validated", false); + if (validated && !json.has("meta")) { + throw new IllegalStateException("It's validated, why doesn't it have meta??"); + } + if (validated) { + meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); + engineResult = meta.engineResult(); + txn = (Transaction) STObject.fromJSONObject(json); + hash = txn.get(Hash256.hash); + ledgerIndex = new UInt32(json.getLong("ledger_index")); + + } + } else if (resultMessageSource == Source.request_account_tx) { + validated = json.optBoolean("validated", false); + if (validated && !json.has("meta")) { + throw new IllegalStateException("It's validated, why doesn't it have meta??"); + } + if (validated) { + JSONObject tx = json.getJSONObject("tx"); + meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); + engineResult = meta.engineResult(); + this.txn = (Transaction) STObject.fromJSONObject(tx); + hash = this.txn.get(Hash256.hash); + ledgerIndex = new UInt32(tx.getLong("ledger_index")); + } + } else if (resultMessageSource == Source.request_account_tx_binary || resultMessageSource == Source.request_tx_binary) { + validated = json.optBoolean("validated", false); + if (validated && !json.has("meta")) { + throw new IllegalStateException("It's validated, why doesn't it have meta??"); + } + if (validated) { + /* + { + "ledger_index": 3378767, + "meta": "201 ...", + "tx_blob": "120 ...", + "validated": true + }, + */ + boolean account_tx = resultMessageSource == Source.request_account_tx_binary; + + String tx = json.getString(account_tx ? "tx_blob" : "tx"); + byte[] decodedTx = B16.decode(tx); + meta = (TransactionMeta) STObject.fromHex(json.getString("meta")); + this.txn = (Transaction) STObject.fromBytes(decodedTx); + + if (account_tx) { + hash = Index.transactionID(decodedTx); + } else { + hash = Hash256.fromHex(json.getString("hash")); + } + this.txn.put(Field.hash, hash); + + engineResult = meta.engineResult(); + ledgerIndex = new UInt32(json.getLong("ledger_index")); + } + } + } + + @Override + public String toString() { + JSONObject object = toJSON(); + return object.toString(); + } + + public JSONObject toJSON() { + JSONObject o = new JSONObject(); + o.put("tx", txn.toJSON()); + o.put("meta", meta.toJSON()); + o.put("ledger_index", ledgerIndex); + o.put("hash", hash.toHex()); + return o; + } + + public TransactionResult copy() { + TransactionMeta metaCopy = (TransactionMeta) STObject.fromBytes(meta.toBytes()); + Transaction txnCopy = (Transaction) STObject.fromBytes(txn.toBytes()); + return new TransactionResult(ledgerIndex.longValue(), hash, txnCopy, metaCopy); + } + + public JSONObject toJSONBinary() { + JSONObject o = new JSONObject(); + + o.put("hash", hash.toHex()); + o.put("meta", meta.toHex()); + o.put("tx", txn.toHex()); + o.put("ledger_index", ledgerIndex); + + return o; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java new file mode 100644 index 0000000000..56440a9bf1 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java @@ -0,0 +1,94 @@ +package com.ripple.core.types.known.tx.signed; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.BytesList; +import com.ripple.core.serialized.MultiSink; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +import java.util.Arrays; + +public class SignedTransaction { + private SignedTransaction(Transaction of) { + // TODO: is this just over kill ? + txn = (Transaction) STObject.fromBytes(of.toBytes()); + } + + protected SignedTransaction() { + } + + public Transaction txn; + public Hash256 hash; + + public byte[] signingData; + public byte[] previousSigningData; + public String tx_blob; + + public static SignedTransaction fromTx(Transaction tx) { + return new SignedTransaction(tx); + } + + public void prepare(byte[] pubKeyBytes) { + prepare(pubKeyBytes,null, null, null); + } + + public void prepare(byte[] pubKeyBytes, + Amount fee, + UInt32 Sequence, + UInt32 lastLedgerSequence) { + + Blob pubKey = new Blob(pubKeyBytes); + + // This won't always be specified + if (lastLedgerSequence != null) { + txn.put(UInt32.LastLedgerSequence, lastLedgerSequence); + } + if (Sequence != null) { + txn.put(UInt32.Sequence, Sequence); + } + if (fee != null) { + txn.put(Amount.Fee, fee); + } + + txn.signingPubKey(pubKey); + + if (Transaction.CANONICAL_FLAG_DEPLOYED) { + txn.setCanonicalSignatureFlag(); + } + + txn.checkFormat(); + signingData = txn.signingData(); + if (previousSigningData != null && Arrays.equals(signingData, previousSigningData)) { + return; + } + } + + public void addSign(byte[] signature) { + try { + txn.txnSignature(new Blob(signature)); + + BytesList blob = new BytesList(); + HalfSha512 id = HalfSha512.prefixed256(HashPrefix.transactionID); + + txn.toBytesSink(new MultiSink(blob, id)); + tx_blob = blob.bytesHex(); + hash = id.finish(); + } catch (Exception e) { + // electric paranoia + previousSigningData = null; + throw new RuntimeException(e); + } /*else {*/ + previousSigningData = signingData; + // } + } + + public TransactionType transactionType() { + return txn.transactionType(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java new file mode 100644 index 0000000000..0e8a1c9672 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java @@ -0,0 +1,46 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.hash.Hash128; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class AccountSet extends Transaction{ + public AccountSet() { + super(TransactionType.AccountSet); + } + public UInt32 transferRate() {return get(UInt32.TransferRate);} + public UInt32 walletSize() {return get(UInt32.WalletSize);} + public UInt32 setFlag() {return get(UInt32.SetFlag);} + public UInt32 clearFlag() {return get(UInt32.ClearFlag);} + public Hash128 emailHash() {return get(Hash128.EmailHash);} + public Hash256 walletLocator() {return get(Hash256.WalletLocator);} + public Blob messageKey() {return get(Blob.MessageKey);} + public Blob domain() {return get(Blob.Domain);} + public UInt8 tickSize() {return get(UInt8.TickSize);} + + public void transferRate(UInt32 val) {put(Field.TransferRate, val);} + public void walletSize(UInt32 val) {put(Field.WalletSize, val);} + public void setFlag(UInt32 val) {put(Field.SetFlag, val);} + public void clearFlag(UInt32 val) {put(Field.ClearFlag, val);} + public void emailHash(Hash128 val) {put(Field.EmailHash, val);} + public void walletLocator(Hash256 val) {put(Field.WalletLocator, val);} + public void messageKey(Blob val) {put(Field.MessageKey, val);} + public void domain(Blob val) {put(Field.Domain, val);} + public void tickSize(UInt8 val) { put(UInt8.TickSize, val);} + + public boolean hasTransferRate() {return has(UInt32.TransferRate);} + public boolean hasWalletSize() {return has(UInt32.WalletSize);} + public boolean hasSetFlag() {return has(UInt32.SetFlag);} + public boolean hasClearFlag() {return has(UInt32.ClearFlag);} + public boolean hasEmailHash() {return has(Hash128.EmailHash);} + public boolean hasWalletLocator() {return has(Hash256.WalletLocator);} + public boolean hasMessageKey() {return has(Blob.MessageKey);} + public boolean hasDomain() {return has(Blob.Domain);} + public boolean hasTickSize() {return has(UInt8.TickSize);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java new file mode 100644 index 0000000000..f5b961f514 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java @@ -0,0 +1,14 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class CheckCancel extends Transaction { + public CheckCancel() { + super(TransactionType.CheckCancel); + } + + public Hash256 checkID() {return get(Hash256.CheckID);} + public void checkID(Hash256 val) { put(Hash256.CheckID, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java new file mode 100644 index 0000000000..8eba2458e9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java @@ -0,0 +1,23 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class CheckCash extends Transaction { + public CheckCash() { + super(TransactionType.CheckCash); + } + + public boolean hasAmount() {return has(Amount.Amount);} + public boolean hasDeliverMin() {return has(Amount.DeliverMin);} + + public Hash256 checkID() {return get(Hash256.CheckID);} + public Amount amount() {return get(Amount.Amount);} + public Amount deliverMin() {return get(Amount.DeliverMin);} + + public void checkID(Hash256 val) { put(Hash256.CheckID, val);} + public void amount(Amount val) { put(Amount.Amount, val);} + public void deliverMin(Amount val) { put(Amount.DeliverMin, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java new file mode 100644 index 0000000000..b8e75a9b0f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java @@ -0,0 +1,30 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class CheckCreate extends Transaction { + public CheckCreate() { + super(TransactionType.CheckCreate); + } + + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} + + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void invoiceID(Hash256 val) { put(Hash256.InvoiceID, val);} + public void sendMax(Amount val) { put(Amount.SendMax, val);} + public void destination(AccountID val) { put(AccountID.Destination, val); } + + public AccountID destination() {return get(AccountID.Destination);} + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public Hash256 invoiceID() {return get(Hash256.InvoiceID);} + public Amount sendMax() {return get(Amount.SendMax);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java new file mode 100644 index 0000000000..68f08cde32 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java @@ -0,0 +1,19 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class DepositPreauth extends Transaction { + public DepositPreauth() { + super(TransactionType.DepositPreauth); + } + public boolean hasAuthorize() {return has(AccountID.Authorize);} + public AccountID authorize() {return get(AccountID.Authorize);} + public void authorize(AccountID val) { put(AccountID.Authorize, val);} + + public boolean hasUnauthorize() {return has(AccountID.Unauthorize);} + public AccountID unauthorize() {return get(AccountID.Unauthorize);} + public void unauthorize(AccountID val) { put(AccountID.Unauthorize, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java new file mode 100644 index 0000000000..ab435bacda --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java @@ -0,0 +1,18 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class EscrowCancel extends Transaction { + public EscrowCancel() { + super(TransactionType.EscrowCancel); + } + + public UInt32 offerSequence() {return get(UInt32.OfferSequence);} + public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} + public AccountID owner() {return get(AccountID.Owner);} + public void owner(AccountID val) { put(AccountID.Owner, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java new file mode 100644 index 0000000000..3587a6c191 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java @@ -0,0 +1,33 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class EscrowCreate extends Transaction { + public EscrowCreate() { + super(TransactionType.EscrowCreate); + } + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} + public boolean hasFinishAfter() {return has(UInt32.FinishAfter);} + public boolean hasCondition() {return has(Blob.Condition);} + + public Amount amount() {return get(Amount.Amount);} + public AccountID destination() {return get(AccountID.Destination);} + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} + public UInt32 finishAfter() {return get(UInt32.FinishAfter);} + public Blob condition() {return get(Blob.Condition);} + + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} + public void finishAfter(UInt32 val) { put(UInt32.FinishAfter, val);} + public void amount(Amount val) { put(Amount.Amount, val);} + public void condition(Blob val) { put(Blob.Condition, val);} + public void destination(AccountID val) { put(AccountID.Destination, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java new file mode 100644 index 0000000000..7b552e768d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java @@ -0,0 +1,27 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class EscrowFinish extends Transaction { + public EscrowFinish() { + super(TransactionType.EscrowFinish); + } + + public boolean hasFulfillment() {return has(Blob.Fulfillment);} + public boolean hasCondition() {return has(Blob.Condition);} + + public UInt32 offerSequence() {return get(UInt32.OfferSequence);} + public Blob fulfillment() {return get(Blob.Fulfillment);} + public Blob condition() {return get(Blob.Condition);} + public AccountID owner() {return get(AccountID.Owner);} + + public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} + public void fulfillment(Blob val) { put(Blob.Fulfillment, val);} + public void condition(Blob val) { put(Blob.Condition, val);} + public void owner(AccountID val) { put(AccountID.Owner, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java new file mode 100644 index 0000000000..461d6cac09 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java @@ -0,0 +1,13 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class OfferCancel extends Transaction { + public OfferCancel() { + super(TransactionType.OfferCancel); + } + public UInt32 offerSequence() {return get(UInt32.OfferSequence);} + public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java new file mode 100644 index 0000000000..dbb783479d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java @@ -0,0 +1,25 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class OfferCreate extends Transaction { + public OfferCreate() { + super(TransactionType.OfferCreate); + } + public UInt32 expiration() {return get(UInt32.Expiration);} + public UInt32 offerSequence() {return get(UInt32.OfferSequence);} + public Amount takerPays() {return get(Amount.TakerPays);} + public Amount takerGets() {return get(Amount.TakerGets);} + public void expiration(UInt32 val) {put(Field.Expiration, val);} + public void offerSequence(UInt32 val) {put(Field.OfferSequence, val);} + public void takerPays(Amount val) {put(Field.TakerPays, val);} + public void takerGets(Amount val) {put(Field.TakerGets, val);} + + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasOfferSequence() {return has(UInt32.OfferSequence);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java new file mode 100644 index 0000000000..10da726d71 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java @@ -0,0 +1,39 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.PathSet; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class Payment extends Transaction { + public Payment() { + super(TransactionType.Payment); + } + + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public Hash256 invoiceID() {return get(Hash256.InvoiceID);} + public Amount amount() {return get(Amount.Amount);} + public Amount sendMax() {return get(Amount.SendMax);} + public AccountID destination() {return get(AccountID.Destination);} + + public PathSet paths() {return get(PathSet.Paths);} + public Amount deliverMin() {return get(Amount.DeliverMin);} + + public void destinationTag(UInt32 val) {put(Field.DestinationTag, val);} + public void invoiceID(Hash256 val) {put(Field.InvoiceID, val);} + public void deliverMin(Amount val) { put(Amount.DeliverMin, val);} + public void amount(Amount val) {put(Field.Amount, val);} + public void sendMax(Amount val) {put(Field.SendMax, val);} + public void destination(AccountID val) {put(Field.Destination, val);} + public void paths(PathSet val) {put(Field.Paths, val);} + + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} + public boolean hasSendMax() {return has(Amount.SendMax);} + public boolean hasDeliverMin() {return has(Amount.DeliverMin);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java new file mode 100644 index 0000000000..8632dbd8b3 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java @@ -0,0 +1,31 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class PaymentChannelClaim extends Transaction { + public PaymentChannelClaim() { + super(TransactionType.PaymentChannelClaim); + } + + public boolean hasAmount() {return has(Amount.Amount);} + public boolean hasBalance() {return has(Amount.Balance);} + public boolean hasPublicKey() {return has(Blob.PublicKey);} + public boolean hasSignature() {return has(Blob.Signature);} + + public void channel(Hash256 val) { put(Hash256.Channel, val);} + public void amount(Amount val) { put(Amount.Amount, val);} + public void balance(Amount val) { put(Amount.Balance, val);} + public void publicKey(Blob val) { put(Blob.PublicKey, val);} + public void signature(Blob val) { put(Blob.Signature, val);} + + public Hash256 channel() {return get(Hash256.Channel);} + public Amount amount() {return get(Amount.Amount);} + public Amount balance() {return get(Amount.Balance);} + public Blob publicKey() {return get(Blob.PublicKey);} + public Blob signature() {return get(Blob.Signature);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java new file mode 100644 index 0000000000..2475c637e5 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java @@ -0,0 +1,32 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.Blob; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class PaymentChannelCreate extends Transaction { + public PaymentChannelCreate() { + super(TransactionType.PaymentChannelCreate); + } + + public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} + public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} + + public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} + public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} + public void settleDelay(UInt32 val) { put(UInt32.SettleDelay, val);} + public void amount(Amount val) { put(Amount.Amount, val);} + public void publicKey(Blob val) { put(Blob.PublicKey, val);} + public void destination(AccountID val) { put(AccountID.Destination, val);} + + public UInt32 destinationTag() {return get(UInt32.DestinationTag);} + public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} + public UInt32 settleDelay() {return get(UInt32.SettleDelay);} + public Amount amount() {return get(Amount.Amount);} + public Blob publicKey() {return get(Blob.PublicKey);} + public AccountID destination() {return get(AccountID.Destination);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java new file mode 100644 index 0000000000..85ccff90f4 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java @@ -0,0 +1,24 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class PaymentChannelFund extends Transaction { + public PaymentChannelFund() { + super(TransactionType.PaymentChannelFund); + } + public boolean hasExpiration() {return has(UInt32.Expiration);} + + public UInt32 expiration() {return get(UInt32.Expiration);} + public Hash256 channel() {return get(Hash256.Channel);} + public Amount amount() {return get(Amount.Amount);} + + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void channel(Hash256 val) { put(Hash256.Channel, val);} + public void amount(Amount val) { put(Amount.Amount, val);} + +} + diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java new file mode 100644 index 0000000000..5d139c75f9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java @@ -0,0 +1,14 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class SetRegularKey extends Transaction { + public SetRegularKey() { + super(TransactionType.SetRegularKey); + } + public boolean hasRegularKey() {return has(AccountID.RegularKey);} + public AccountID regularKey() {return get(AccountID.RegularKey);} + public void regularKey(AccountID val) { put(AccountID.RegularKey, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java new file mode 100644 index 0000000000..830381f8ff --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java @@ -0,0 +1,20 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.STArray; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class SignerListSet extends Transaction { + public SignerListSet() { + super(TransactionType.SignerListSet); + } + public boolean hasSignerEntries() {return has(STArray.SignerEntries);} + + public UInt32 signerQuorum() {return get(UInt32.SignerQuorum);} + public STArray signerEntries() {return get(STArray.SignerEntries);} + + public void signerQuorum(UInt32 val) { put(UInt32.SignerQuorum, val);} + public void signerEntries(STArray val) { put(STArray.SignerEntries, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java new file mode 100644 index 0000000000..a75f525e52 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java @@ -0,0 +1,17 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class TicketCancel extends Transaction { + public TicketCancel() { + super(TransactionType.TicketCancel); + } + public Hash256 ticketID() { + return get(Hash256.TicketID); + } + public void ticketID(Hash256 id) { + put(Hash256.TicketID, id); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java new file mode 100644 index 0000000000..4e8ac5fb3f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java @@ -0,0 +1,22 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.AccountID; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class TicketCreate extends Transaction { + public TicketCreate() { + super(TransactionType.TicketCreate); + } + + public boolean hasExpiration() {return has(UInt32.Expiration);} + public boolean hasTarget() {return has(AccountID.Target);} + + public UInt32 expiration() {return get(UInt32.Expiration);} + public AccountID target() {return get(AccountID.Target);} + + public void expiration(UInt32 val) { put(UInt32.Expiration, val);} + public void target(AccountID val) { put(AccountID.Target, val);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java new file mode 100644 index 0000000000..ba5702c2e4 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java @@ -0,0 +1,25 @@ +package com.ripple.core.types.known.tx.txns; + +import com.ripple.core.coretypes.Amount; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class TrustSet extends Transaction { + public TrustSet() { + super(TransactionType.TrustSet); + } + + public UInt32 qualityIn() {return get(UInt32.QualityIn);} + public UInt32 qualityOut() {return get(UInt32.QualityOut);} + public Amount limitAmount() {return get(Amount.LimitAmount);} + public void qualityIn(UInt32 val) {put(Field.QualityIn, val);} + public void qualityOut(UInt32 val) {put(Field.QualityOut, val);} + public void limitAmount(Amount val) {put(Field.LimitAmount, val);} + + public boolean hasQualityIn() {return has(UInt32.QualityIn);} + public boolean hasQualityOut() {return has(UInt32.QualityOut);} + public boolean hasLimitAmount() {return has(Amount.LimitAmount);} + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java new file mode 100644 index 0000000000..b65fc929e6 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java @@ -0,0 +1,17 @@ +package com.ripple.core.types.known.tx.txns.pseudo; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class EnableAmendment extends Transaction { + public EnableAmendment() { + super(TransactionType.EnableAmendment); + } + + public UInt32 ledgerSequence() {return get(UInt32.LedgerSequence);} + public void ledgerSequence(UInt32 val) { put(UInt32.LedgerSequence, val);} + public Hash256 amendment() {return get(Hash256.Amendment);} + public void amendment(Hash256 val) { put(Hash256.Amendment, val);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java new file mode 100644 index 0000000000..800f13e35f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java @@ -0,0 +1,25 @@ +package com.ripple.core.types.known.tx.txns.pseudo; + +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.serialized.enums.TransactionType; +import com.ripple.core.types.known.tx.Transaction; + +public class SetFee extends Transaction { + public SetFee() { + super(TransactionType.SetFee); + } + public boolean hasLedgerSequence() {return has(UInt32.LedgerSequence);} + + public void ledgerSequence(UInt32 val) { put(UInt32.LedgerSequence, val);} + public void referenceFeeUnits(UInt32 val) { put(UInt32.ReferenceFeeUnits, val);} + public void reserveBase(UInt32 val) { put(UInt32.ReserveBase, val);} + public void reserveIncrement(UInt32 val) { put(UInt32.ReserveIncrement, val);} + public void baseFee(UInt64 val) { put(UInt64.BaseFee, val);} + + public UInt32 ledgerSequence() {return get(UInt32.LedgerSequence);} + public UInt32 referenceFeeUnits() {return get(UInt32.ReferenceFeeUnits);} + public UInt32 reserveBase() {return get(UInt32.ReserveBase);} + public UInt32 reserveIncrement() {return get(UInt32.ReserveIncrement);} + public UInt64 baseFee() {return get(UInt64.BaseFee);} +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java b/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java new file mode 100644 index 0000000000..240b0f6da8 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java @@ -0,0 +1,109 @@ +package com.ripple.core.types.ledger; + +import com.ripple.core.binary.STReader; +import com.ripple.core.coretypes.RippleDate; +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.coretypes.uint.UInt64; +import com.ripple.core.coretypes.uint.UInt8; +import com.ripple.core.serialized.BinaryParser; +import com.ripple.core.serialized.BytesSink; +import org.json.JSONObject; +import org.json.JSONWriter; + +import java.util.Date; + +public class LedgerHeader { + // Always 0x4C475200 (LWR) (Secures signed objects) + public UInt32 version = HashPrefix.ledgerMaster.uInt32(); + + public UInt32 sequence; // Ledger Sequence (0 for genesis ledger) + public UInt64 totalXRP; // + public Hash256 previousLedger; // The hash of the previous ledger (0 for genesis ledger) + public Hash256 transactionHash; // The hash of the transaction tree's root node. + public Hash256 stateHash; // The hash of the state tree's root node. + public UInt32 parentCloseTime; // The time the previous ledger closed + public UInt32 closeTime; // UTC minute ledger closed encoded as seconds since 1/1/2000 (or 0 for genesis ledger) + public UInt8 closeResolution; // The resolution (in seconds) of the close time + public UInt8 closeFlags; // Flags + + public Date closeDate; + + public static LedgerHeader fromParser(BinaryParser parser) { + return fromReader(new STReader(parser)); + } + public static LedgerHeader fromHex(String ledger_data) { + return LedgerHeader.fromParser(new BinaryParser(ledger_data)); + } + + public static LedgerHeader fromReader(STReader reader) { + LedgerHeader ledger = new LedgerHeader(); + + ledger.sequence = reader.uInt32(); + ledger.totalXRP = reader.uInt64(); + ledger.previousLedger = reader.hash256(); + ledger.transactionHash= reader.hash256(); + ledger.stateHash = reader.hash256(); + ledger.parentCloseTime = reader.uInt32(); + ledger.closeTime = reader.uInt32(); + ledger.closeResolution = reader.uInt8(); + ledger.closeFlags = reader.uInt8(); + + ledger.closeDate = RippleDate.fromSecondsSinceRippleEpoch(ledger.closeTime); + + return ledger; + } + + public void toBytesSink(BytesSink sink) { + sequence.toBytesSink(sink); + totalXRP.toBytesSink(sink); + previousLedger.toBytesSink(sink); + transactionHash.toBytesSink(sink); + stateHash.toBytesSink(sink); + parentCloseTime.toBytesSink(sink); + closeTime.toBytesSink(sink); + closeResolution.toBytesSink(sink); + closeFlags.toBytesSink(sink); + } + + public Hash256 hash() { + HalfSha512 half = HalfSha512.prefixed256(HashPrefix.ledgerMaster); + toBytesSink(half); + return half.finish(); + } + + public void toJSONWriter(JSONWriter writer) { + writer.key("ledger_index"); + writer.value(sequence.toJSON()); + writer.key("total_coins"); + writer.value(totalXRP.toString(10)); + writer.key("parent_hash"); + writer.value(previousLedger.toJSON()); + writer.key("transaction_hash"); + writer.value(transactionHash.toJSON()); + writer.key("account_hash"); + writer.value(stateHash.toJSON()); + writer.key("close_time"); + writer.value(closeTime.toJSON()); + writer.key("close_time_human"); + // TODO + writer.value(RippleDate.gmtString(RippleDate.fromSecondsSinceRippleEpoch(closeTime))); + writer.key("parent_close_time"); + writer.value(parentCloseTime.toJSON()); + writer.key("close_time_resolution"); + writer.value(closeResolution.toJSON()); + writer.key("close_flags"); + writer.value(closeFlags.toJSON()); + } + + public JSONObject toJSON() { + StringBuilder builder = new StringBuilder(); + JSONWriter jsonWriter = new JSONWriter(builder); + jsonWriter.object(); + toJSONWriter(jsonWriter); + jsonWriter.endObject(); + return new JSONObject(builder.toString()); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java new file mode 100644 index 0000000000..c6eaadd3fa --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java @@ -0,0 +1,341 @@ +package com.ripple.core.types.shamap; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.Vector256; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.Index; +import com.ripple.core.coretypes.uint.UInt32; +import com.ripple.core.serialized.enums.LedgerEntryType; +import com.ripple.core.types.known.sle.LedgerEntry; +import com.ripple.core.types.known.sle.LedgerHashes; +import com.ripple.core.types.known.sle.entries.DirectoryNode; +import com.ripple.core.types.known.sle.entries.OfferDirectory; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.json.JSONWriter; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; + +public class AccountState extends ShaMap { + public AccountState() { + super(); + } + public AccountState(boolean isCopy, int depth) { + super(isCopy, depth); + } + + @Override + protected ShaMapInner makeInnerOfSameClass(int depth) { + return new AccountState(true, depth); + } + + private static LedgerHashes newSkipList(Hash256 skipIndex) { + LedgerHashes skip; + skip = new LedgerHashes(); + skip.put(UInt32.Flags, new UInt32(0)); + skip.hashes(new Vector256()); + skip.index(skipIndex); + return skip; + } + + public void updateSkipLists(long currentIndex, Hash256 parentHash) { + long prev = currentIndex - 1; + + if ((prev & 0xFF) == 0) { + Hash256 skipIndex = Index.ledgerHashes(prev); + LedgerHashes skip = createOrUpdateSkipList(skipIndex); + Vector256 hashes = skip.hashes(); + assert hashes.size() <= 256; + hashes.add(parentHash); + skip.put(UInt32.LastLedgerSequence, new UInt32(prev)); + } + + Hash256 skipIndex = Index.ledgerHashes(); + LedgerHashes skip = createOrUpdateSkipList(skipIndex); + Vector256 hashes = skip.hashes(); + + if (hashes.size() > 256) throw new AssertionError(); + if (hashes.size() == 256) { + hashes.remove(0); + } + + hashes.add(parentHash); + skip.put(UInt32.LastLedgerSequence, new UInt32(prev)); + } + + private LedgerHashes createOrUpdateSkipList(Hash256 skipIndex) { + PathToIndex path = pathToIndex(skipIndex); + ShaMapInner top = path.dirtyOrCopyInners(); + LedgerEntryItem item; + + if (path.hasMatchedLeaf()) { + ShaMapLeaf leaf = path.invalidatedPossiblyCopiedLeafForUpdating(); + item = (LedgerEntryItem) leaf.item; + } else { + item = new LedgerEntryItem(newSkipList(skipIndex)); + top.addLeafToTerminalInner(new ShaMapLeaf(skipIndex, item)); + } + return (LedgerHashes) item.entry; + } + + public boolean addLE(LedgerEntry entry) { + LedgerEntryItem item = new LedgerEntryItem(entry); + return addItem(entry.index(), item); + } + + public boolean updateLE(LedgerEntry entry) { + LedgerEntryItem item = new LedgerEntryItem(entry); + return updateItem(entry.index(), item); + } + + public LedgerEntry getLE(Hash256 index) { + LedgerEntryItem item = (LedgerEntryItem) getItem(index); + return item == null ? null : item.value(); + } + + public DirectoryNode getDirectoryNode(Hash256 index) { + return (DirectoryNode) getLE(index); + } + + public Iterable offerDirectories(Hash256 bookBase) { + final QualityIterator iter = qualityIterator(bookBase); + + return new Iterable() { + @Override + public Iterator iterator() { + return new Iterator() { + @Override + public boolean hasNext() { + boolean hasNext = iter.hasNext(); + // In case we need to skip some entries + if (hasNext && !(iter.next() instanceof OfferDirectory)) { + return this.hasNext(); + } + return hasNext; + } + + @Override + public OfferDirectory next() { + return (OfferDirectory) iter.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + public void writeEntriesArray(final JSONWriter writer) { + writer.array(); + walkEntries(entry -> writer.value(entry.toJSON())); + writer.endArray(); + } + + // Assumes shamap won't be modified during iteration, not unusual for an + // iterator. + public class QualityIterator implements Iterator { + ShaMapInner[] inners = new ShaMapInner[64]; + Hash256 base; + Hash256 end; + int[] selections = new int[64]; + int commonNibblets; + int depth; + ShaMapLeaf next; + private boolean finished = false; + + public QualityIterator(Hash256 start) { + base = start; + depth=0; + end = Index.bookEnd(start); + ShaMapInner inner = AccountState.this; + setInner(inner); + setSelected(start.nibblet(depth)); + findCommonNibblets(); + } + + private void findCommonNibblets() { + for (int i = 0; i < 64; i++) { + if (base.nibblet(i) == end.nibblet(i)) { + commonNibblets = i; + } else { + break; + } + } + } + + private void setInner(ShaMapInner inner) { + inners[depth] = inner; + } + + private void findNext() { + next = null; + + while (true) { + while (selected() > 15) { + depth--; + incrementSelection(); + } + if (depth < commonNibblets && selected() > end.nibblet(depth)) { + finished = true; + break; + } + ShaMapInner current = currentInner(); + ShaMapNode branch = current.getBranch(selected()); + if (branch == null) { + incrementSelection(); + } else if (branch.isInner()) { + depth++; + setInner(branch.asInner()); + setSelected(base.nibblet(depth)); + } else if (branch.isLeaf()) { + ShaMapLeaf leaf = branch.asLeaf(); + Hash256 leafIndex = leaf.index; + boolean leafIsOnPathToBase = depth < commonNibblets; + if ( leafIsOnPathToBase || leafIndex.compareTo(base) > 0 && + leafIndex.compareTo(end) < 0) { + next = leaf; + incrementSelection(); + } else { + finished = true; + } + break; + } + } + } + + private ShaMapInner currentInner() { + return inners[depth]; + } + private int selected() { + return selections[depth]; + } + private void setSelected(int nibblet) { + selections[depth] = nibblet; + } + private void incrementSelection() { + selections[depth]++; + } + + @Override + public boolean hasNext() { + findNext(); + return !finished && next != null; + } + @Override + public LedgerEntry next() { + // Just assume hasNext has been called + LedgerEntryItem item = (LedgerEntryItem) next.item; + return item.entry; + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + public QualityIterator qualityIterator(final Hash256 bookBase) { + return new QualityIterator(bookBase); + } + + public Iterable directoryIterator(OfferDirectory forQuality) { + // TODO: create an actual iterator + Vector256 indexes = new Vector256(); + OfferDirectory cursor = forQuality; + + while (cursor != null) { + indexes.addAll(cursor.indexes()); + if (cursor.hasNextIndex()) { + LedgerEntry le = getLE(cursor.nextIndex()); + if (le instanceof OfferDirectory) { + cursor = (OfferDirectory) le; + } + else { + break; + } + } + else { + break; + } + } + return indexes; + } + + public void walkEntries(final LedgerEntryVisitor walker) { + walkLeaves(leaf -> { + LedgerEntryItem item = (LedgerEntryItem) leaf.item; + walker.onEntry(item.entry); + }); + } + + // TODO + public Hash256 getNextIndex(Hash256 nextIndex, Hash256 bookEnd) { + return null; + } + + @Override + public AccountState copy() { + return (AccountState) super.copy(); + } + + public static AccountState loadFromLedgerDump(String filePath) { + try { + FileReader reader = new FileReader(filePath); + return loadFromLedgerDump(reader); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + public static AccountState loadFromLedgerDump(Reader reader) { + try { + JsonFactory jsonFactory = new JsonFactory(); + JsonParser parser = jsonFactory.createParser(reader); + JsonToken jsonToken = parser.nextToken(); + if (jsonToken != JsonToken.START_OBJECT) { + throw new AssertionError(); + } + + String accountState = "accountState"; + + // TODO: + while (parser.nextToken() != null) { + String currentName = parser.getCurrentName(); + if (currentName.equals(accountState)) { + break; + } + } + + if (!parser.getCurrentName().equals("accountState")) { + throw new IllegalStateException("No `accountState` field found!"); + } + + AccountState state = new AccountState(); + ObjectMapper mapper = new ObjectMapper(); + if (parser.nextToken() != JsonToken.START_ARRAY) { + throw new AssertionError(); + } + + while (parser.nextToken() != JsonToken.END_ARRAY) { + TreeNode treeNode = mapper.readTree(parser); + state.addLE((LedgerEntry) STObject.fromJacksonObject((ObjectNode) treeNode)); + } + return state; + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java new file mode 100644 index 0000000000..1b43203db7 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java @@ -0,0 +1,320 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.fields.Field; +import com.ripple.core.types.known.sle.LedgerEntry; +import com.ripple.core.types.known.sle.ThreadedLedgerEntry; +import com.ripple.core.types.known.sle.entries.*; +import com.ripple.core.types.known.tx.result.AffectedNode; +import com.ripple.core.types.known.tx.result.TransactionResult; + +import java.util.*; + +public class AccountStateBuilder { + private AccountState state; + private AccountState previousState = null; + private long targetLedgerIndex; + public long nextTransactionIndex = 0; + private Hash256 targetAccountHash; + public long totalTransactions = 0; + + private TreeSet directoriesModifiedMoreThanOnceByTransaction = new TreeSet<>(); + private TreeSet directoriesModifiedByTransaction = new TreeSet<>(); + public TreeSet ledgerModifiedEntries = new TreeSet<>(); + public TreeSet ledgerDeletedEntries = new TreeSet<>(); + + public boolean sortedDirectories = true; + + public void resetModified() { + ledgerModifiedEntries.clear(); + ledgerDeletedEntries.clear(); + directoriesModifiedMoreThanOnceByTransaction.clear(); + } + + public AccountStateBuilder(AccountState state, long targetLedgerIndex) { + this.state = state; + setStateCheckPoint(); + this.targetLedgerIndex = targetLedgerIndex; + } + + public void onLedgerClose(long ledgerIndex, Hash256 accountHash, Hash256 parentHash) { + state.updateSkipLists(ledgerIndex, parentHash); + targetLedgerIndex = ledgerIndex; + targetAccountHash = accountHash; + nextTransactionIndex = 0; + } + + public void setStateCheckPoint() { + previousState = state.copy(); + } + + public void onTransaction(TransactionResult tr) { + System.out.println("adding tx: " + tr.hash); + if (tr.meta.transactionIndex().longValue() != nextTransactionIndex) throw new AssertionError(); + if (tr.ledgerIndex.longValue() != targetLedgerIndex + 1) throw new AssertionError(String.format("%d != %d", tr.ledgerIndex.longValue(), targetLedgerIndex + 1)); + nextTransactionIndex++; + totalTransactions++; + directoriesModifiedByTransaction = new TreeSet<>(); + + for (AffectedNode an : sortedAffectedNodes(tr)) { + Hash256 id = an.ledgerIndex(); + LedgerEntry le = an.nodeAsFinal(); + + if (an.isCreatedNode()) { + ledgerModifiedEntries.add(id); + ledgerDeletedEntries.remove(id); + le.setDefaults(); + state.addLE(le); + + if (le instanceof Offer) { + Offer offer = (Offer) le; + offer.setOfferDefaults(); // TODO / TODO + + for (Hash256 directory : offer.directoryIndexes()) { + DirectoryNode dn = getDirectoryForUpdating(directory); + Hash256 index = offer.index(); + addToDirectoryNode(dn, index); + } + } else if (le instanceof RippleState) { + RippleState state = (RippleState) le; + + for (Hash256 directory : state.directoryIndexes()) { + DirectoryNode dn = getDirectoryForUpdating(directory); + addToDirectoryNode(dn, state.index()); + } + } + + if (le instanceof IndexedLedgerEntry) { + IndexedLedgerEntry owned = (IndexedLedgerEntry) le; + for (Hash256 directory : owned.ownerDirectoryIndexes(tr.txn)) { + DirectoryNode dn = getDirectoryForUpdating(directory); + addToDirectoryNode(dn, owned.index()); + } + } + + if (le instanceof ThreadedLedgerEntry) { + ThreadedLedgerEntry tle = (ThreadedLedgerEntry) le; + tle.previousTxnID(tr.hash); + tle.previousTxnLgrSeq(tr.ledgerIndex); + } + } else if (an.isDeletedNode()) { + ledgerModifiedEntries.remove(id); + ledgerDeletedEntries.add(id); + directoriesModifiedMoreThanOnceByTransaction.remove(id); + state.removeLeaf(id); + if (le instanceof Offer) { + Offer offer = (Offer) le; + for (Hash256 directory : offer.directoryIndexes()) { + DirectoryNode dn = getDirectoryForUpdating(directory); + if (dn != null) { +// Hash256 index = offer.index(); + if (dn.owner() != null) { + deleteFromDirectoryUnstable(offer, dn); + } else { + deleteFromDirectoryStable(offer, dn); + } + } + } + } else if (le instanceof RippleState) { + RippleState state = (RippleState) le; + for (Hash256 directory : state.directoryIndexes()) { + DirectoryNode dn = getDirectoryForUpdating(directory); + if (dn != null) { + deleteFromDirectoryUnstable(le, dn); + } + } + } else if (le instanceof IndexedLedgerEntry) { + IndexedLedgerEntry owned = (IndexedLedgerEntry) le; + for (Hash256 directory : owned.ownerDirectoryIndexes(tr.txn)) { + DirectoryNode dn = getDirectoryForUpdating(directory); + deleteFromDirectoryUnstable(le, dn); + } + } + } else if (an.isModifiedNode()) { + ledgerModifiedEntries.add(id); + ShaMapLeaf leaf = state.getLeafForUpdating(id); + LedgerEntryItem item = (LedgerEntryItem) leaf.item; + LedgerEntry leModded = item.entry; + + if (le instanceof ThreadedLedgerEntry) { + ThreadedLedgerEntry tle = (ThreadedLedgerEntry) le; + tle.previousTxnID(tr.hash); + tle.previousTxnLgrSeq(tr.ledgerIndex); + } + for (Field field : le) { + // Already have the `index` + if (field == Field.LedgerIndex) { + continue; + } + leModded.put(field, le.get(field)); + } + // Find all removed fields + ArrayList removed = new ArrayList<>(); + for (Field field : leModded) { + if (an.removedField(field)) { + removed.add(field); + } + } + removed.forEach(leModded::remove); + } + } + } + + private void deleteFromDirectoryUnstable(LedgerEntry b4, DirectoryNode dn) { + boolean b = directoryRemoveUnstable(dn, b4.index()); + DirectoryNode cursor = dn; + + if (!b) { + while (cursor.indexNext() != null) { + cursor = getDirectoryForUpdating(cursor.nextIndex()); + b = directoryRemoveUnstable(cursor, b4.index()); + if (b) { + break; + } + } + } +// + if (!b) { + cursor = dn; + while (cursor.indexPrevious() != null) { + cursor = getDirectoryForUpdating(cursor.prevIndex()); + b = directoryRemoveUnstable(cursor, b4.index()); + if (b) { + break; + } + } + } + } + private void deleteFromDirectoryStable(LedgerEntry b4, DirectoryNode dn) { + boolean b = directoryRemoveStable(dn, b4.index()); + DirectoryNode cursor = dn; + + if (!b) { + while (cursor.hasIndexPrevious()) { + cursor = getDirectoryForUpdating(cursor.prevIndex()); + b = directoryRemoveStable(cursor, b4.index()); + if (b) { + break; + } + } + } + if (!b) { + while (cursor.indexNext() != null) { + cursor = getDirectoryForUpdating(cursor.nextIndex()); + b = directoryRemoveStable(cursor, b4.index()); + if (b) { + break; + } + } + } + } + + public static Collection makeCollection(Iterable iter) { + Collection list = new ArrayList<>(); + for (E item : iter) { + list.add(item); + } + return list; + } + private ArrayList sortedAffectedNodes(TransactionResult tr) { + ArrayList sorted = new ArrayList<>(makeCollection(tr.meta.affectedNodes())); + sorted.sort(Comparator.comparingInt(this::getOrdinal)); + return sorted; + } + + private int getOrdinal(AffectedNode o1) { + switch (o1.ledgerEntryType()) { + case DirectoryNode: + return 10; + case RippleState: + return 20; + case Offer: + return 30; + case Escrow: + case SignerList: + case PayChannel: + return 21; + default: + return 40; + } + } + + private void onDirectoryModified(DirectoryNode dn) { + Hash256 index = dn.index(); + if (directoriesModifiedByTransaction.contains(index)) { + directoriesModifiedMoreThanOnceByTransaction.add(index); + } + else { + directoriesModifiedByTransaction.add(index); + } + } + private boolean directoryRemoveStable(DirectoryNode dn, Hash256 index) { + onDirectoryModified(dn); + return dn.indexes().remove(index); + } + private boolean directoryRemoveUnstable(DirectoryNode dn, Hash256 index) { + onDirectoryModified(dn); + if (sortedDirectories) { + return dn.indexes().remove(index); + } else { + return dn.indexes().removeUnstable(index); + } + } + private void addToDirectoryNode(DirectoryNode dn, Hash256 index) { + onDirectoryModified(dn); + if (dn.exchangeRate() != null) { + dn.indexes().add(index); + } else { + dn.indexes().add(index); + if (sortedDirectories) { + Collections.sort(dn.indexes()); + } + } + } + private DirectoryNode getDirectoryForUpdating(Hash256 directoryIndex) { + ShaMapLeaf leaf = state.getLeafForUpdating(directoryIndex); + if (leaf == null) { + return null; + } + LedgerEntryItem lei = (LedgerEntryItem) leaf.item; + return (DirectoryNode) lei.entry; + } + + public AccountState state() { + return state; + } + + public long currentLedgerIndex() { + return targetLedgerIndex; + } + + public String targetAccountHashHex() { + return targetAccountHash.toHex(); + } + public Hash256 targetAccountHash() { + return targetAccountHash; + } + + public TreeSet directoriesWithIndexesOutOfOrder() { + TreeSet ret = new TreeSet<>(); + for (Hash256 hash256 : directoriesModifiedMoreThanOnceByTransaction) { + DirectoryNode dn = state.getDirectoryNode(hash256); + if (dn.owner() != null) { + ret.add(hash256); + } + } + return ret; + } + + public boolean bad() { + return !state.hash().equals(targetAccountHash); + } + + public AccountState previousState() { + return previousState; + } + + public void setState(AccountState map) { + state = map; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java new file mode 100644 index 0000000000..11365302b5 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java @@ -0,0 +1,37 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; + +public class BytesItem extends ShaMapItem { + private byte[] item; + + public BytesItem(byte[] item) { + this.item = item; + } + + @Override + void toBytesSink(BytesSink sink) { + sink.add(item); + } + + @Override + public ShaMapItem copy() { + return this; + } + + @Override + public byte[] value() { + return item; + } + + @Override + public Prefix hashPrefix() { + return new Prefix() { + @Override + public byte[] bytes() { + return new byte[0]; + } + }; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java new file mode 100644 index 0000000000..a565baf19b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java @@ -0,0 +1,8 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; + +public interface HashedTreeWalker { + public void onLeaf(Hash256 h, ShaMapLeaf le); + public void onInner(Hash256 h, ShaMapInner inner); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java new file mode 100644 index 0000000000..71f371cebe --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java @@ -0,0 +1,5 @@ +package com.ripple.core.types.shamap; + +public interface LeafWalker { + void onLeaf(ShaMapLeaf shaMapLeaf); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java new file mode 100644 index 0000000000..ea67d4bf0b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java @@ -0,0 +1,45 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.STObject; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.fields.Field; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.types.known.sle.LedgerEntry; + +public class LedgerEntryItem extends ShaMapItem { + public LedgerEntryItem(LedgerEntry entry) { + this.entry = entry; + } + + public LedgerEntry entry; + + @Override + void toBytesSink(BytesSink sink) { + entry.toBytesSink(sink); + } + + @Override + public String toString() { + return entry.prettyJSON(); + } + + @Override + public ShaMapItem copy() { + STObject object = STObject.fromBytes(entry.toBytes()); + LedgerEntry le = (LedgerEntry) object; + // TODO: what about other auxiliary (non serialized) fields + le.index(entry.index()); + return new LedgerEntryItem(le); + } + + @Override + public LedgerEntry value() { + return entry; + } + + @Override + public Prefix hashPrefix() { + return HashPrefix.leafNode; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java new file mode 100644 index 0000000000..6ce639b552 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java @@ -0,0 +1,7 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.types.known.sle.LedgerEntry; + +public interface LedgerEntryVisitor { + public void onEntry(LedgerEntry entry); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java new file mode 100644 index 0000000000..8d1bd98eee --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java @@ -0,0 +1,64 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash256; + +/** + + * This is a toy implementation for illustrative purposes. + */ +public class NodeStore { + /** + * In ripple, all data is stored in a simple binary key/value database. + * The keys are 256 bit binary strings and the values are binary strings of + * arbitrary length. + */ + public static interface KeyValueBackend { + void put(Hash256 key, byte[] content); + byte[] get(Hash256 key); + } + + KeyValueBackend backend; + public NodeStore(KeyValueBackend backend) { + this.backend = backend; + } + /** + * All data stored is keyed by the hash of it's contents. + * Ripple uses the first 256 bits of a sha512 as it's 33 percent + * faster than using sha256. + * + * @return `key` used to store the content + */ + private Hash256 storeContent(byte[] content) { + HalfSha512 hasher = new HalfSha512(); + hasher.update(content); + Hash256 key = hasher.finish(); + storeHashKeyedContent(key, content); + return key; + } + + /** + * @param hash As ripple uses the `hash` of the contents as the + * NodeStore key, `hash` is pervasively used in lieu of + * the term `key`. + */ + private void storeHashKeyedContent(Hash256 hash, byte[] content) { + // Note: The real nodestore actually prepends some metadata, which doesn't + // contribute to the hash. + backend.put(hash, content); // metadata + content + } + + /** + * The complement to `set` api, which together form a simple public interface. + */ + public byte[] get(Hash256 hash) { + return backend.get(hash); + + } + /** + * The complement to `get` api, which together form a simple public interface. + */ + public Hash256 set(byte[] content) { + return storeContent(content); + } +} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java new file mode 100644 index 0000000000..dcc0dfd56e --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java @@ -0,0 +1,156 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Iterator; + +public class PathToIndex { + public Hash256 index; + public ShaMapLeaf leaf; + + private ArrayDeque inners; + private ShaMapInner[] dirtied; + private boolean matched = false; + + public boolean hasLeaf() { + return leaf != null; + } + public boolean leafMatchedIndex() { + return matched; + } + public boolean copyLeafOnUpdate() { + return leaf.version != dirtied[0].version; + } + + int size() { + return inners.size(); + } + + public ShaMapInner top() { + return dirtied[dirtied.length - 1]; + } + + // returns the + public ShaMapInner dirtyOrCopyInners() { + if (maybeCopyOnWrite()) { + int ix = 0; + // We want to make a uniformly accessed array of the inners + dirtied = new ShaMapInner[inners.size()]; + // from depth 0 to 1, to 2, to 3, don't be fooled by the api + Iterator it = inners.descendingIterator(); + + // This is actually the root which COULD be the top of the stack + // Think about it ;) + ShaMapInner top = it.next(); + dirtied[ix++] = top; + top.invalidate(); + + while (it.hasNext()) { + ShaMapInner next = it.next(); + boolean doCopies = next.version != top.version; + + if (doCopies) { + ShaMapInner copy = next.copy(top.version); + copy.invalidate(); + top.setBranch(index, copy); + next = copy; + } else { + next.invalidate(); + } + top = next; + dirtied[ix++] = top; + } + return top; + } else { + copyInnersToDirtiedArray(); + return inners.peekFirst(); + } + } + + public boolean hasMatchedLeaf() { + return hasLeaf() && leafMatchedIndex(); + } + + public void collapseOnlyLeafChildInners() { + assert dirtied != null; + + ShaMapInner next; + ShaMapLeaf onlyChild = null; + + for (int i = dirtied.length - 1; i >= 0; i--) { + next = dirtied[i]; + if (onlyChild != null) { + next.setLeaf(onlyChild); + } + onlyChild = next.onlyChildLeaf(); + if (onlyChild == null) { + break; + } + } + } + + private void copyInnersToDirtiedArray() { + int ix = 0; + dirtied = new ShaMapInner[inners.size()]; + Iterator descending = inners.descendingIterator(); + while (descending.hasNext()) { + ShaMapInner next = descending.next(); + dirtied[ix++] = next; + next.invalidate(); + } + } + + private boolean maybeCopyOnWrite() { + return inners.peekLast().doCoW; + } + + public PathToIndex(ShaMapInner root, Hash256 index) { + this.index = index; + makeStack(root, index); + } + + private void makeStack(ShaMapInner root, Hash256 index) { + inners = new ArrayDeque<>(); + ShaMapInner top = root; + + while (true) { + inners.push(top); + ShaMapNode existing = top.getBranch(index); + if (existing == null) { + break; + } else if (existing.isLeaf()) { + leaf = existing.asLeaf(); + matched = leaf.index.equals(index); + break; + } + else if (existing.isInner()) { + top = existing.asInner(); + } + } + } + + public ShaMapLeaf invalidatedPossiblyCopiedLeafForUpdating() { + assert matched; + if (dirtied == null) { + dirtyOrCopyInners(); + } + ShaMapLeaf theLeaf = leaf; + + if (copyLeafOnUpdate()) { + theLeaf = leaf.copy(); + top().setLeaf(theLeaf); + } + theLeaf.invalidate(); + return theLeaf; + } + + public ArrayList topDownList() { + ArrayList path = new ArrayList<>(); + Iterator shaMapInnerIterator = inners.descendingIterator(); + shaMapInnerIterator.forEachRemaining(path::add); + path.add(leaf); + return path; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md b/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md new file mode 100644 index 0000000000..a78bc3ad73 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md @@ -0,0 +1,319 @@ +Rippled NodeStore +----------------- + +To understand a ShaMap first you must know about the NodeStore. + +```java +/** + + * This is a toy implementation for illustrative purposes. + */ +public class NodeStore { + /** + * In ripple, all data is stored in a simple binary key/value database. + * The keys are 256 bit binary strings and the values are binary strings of + * arbitrary length. + */ + public interface KeyValueBackend { + void put(Hash256 key, byte[] content); + byte[] get(Hash256 key); + } + + KeyValueBackend backend; + public NodeStore(KeyValueBackend backend) { + this.backend = backend; + } + /** + * All data stored is keyed by the hash of it's contents. + * Ripple uses the first 256 bits of a sha512 as it's 33 percent + * faster than using sha256. + * + * @return `key` used to store the content + */ + private Hash256 storeContent(byte[] content) { + Hash256.HalfSha512 hasher = new Hash256.HalfSha512(); + hasher.update(content); + Hash256 key = hasher.finish(); + storeHashKeyedContent(key, content); + return key; + } + + /** + * @param hash As ripple uses the `hash` of the contents as the + * NodeStore key, `hash` is pervasively used in lieu of + * the term `key`. + */ + private void storeHashKeyedContent(Hash256 hash, byte[] content) { + // Note: The real NodeStore actually prepends some metadata, which doesn't + // contribute to the hash. + backend.put(hash, content); // metadata + content + } + + /** + * The complement to `set` api, which together form a simple public interface. + */ + public byte[] get(Hash256 hash) { + return backend.get(hash); + + } + /** + * The complement to `get` api, which together form a simple public interface. + */ + public Hash256 set(byte[] content) { + return storeContent(content); + } +} +``` + +See also: +* [Serialized Types](../../../../../../../../README.md) +* [BinaryFormats.txt (historical)](https://github.com/ripple/rippled/blob/07df5f1f81b0ee1ab641d134ba8e940a90f5297e/BinaryFormats.txt#L2-L6) + +Excerpt from BinaryFormats.txt (historical): + +

+ All signed or hashed objects must have well-defined binary formats at the + byte level. These formats do not have to be the same as the network wire + formats or the forms used for efficient storage or human display. However, + it must always be possible to precisely re-create, byte for byte, any signed + or hashed object. Otherwise, the signatures or hashes cannot be validated. +
+ +Note that currently (26/Jan/2018) the NodeStore stores it in the hashing form. + +What is a ShaMap? +----------------- + +A ShaMap is a special type of tree, used as a way to index values stored in a +`NodeStore` + +Recall that values in the NodeStore are keyed by the hash of their contents. + +But what about identities that change over time? How can you retrieve a certain +version of something? What could be used as an enduring identifier? The value +must have some component[s] that are static over time. These are fed into a +hashing function to create a 256 bit identifier. + +But how is this used? You can only query values by `hash` in the NodeStore. The +hash, as a function of a value would obviously change along with it. + +The identifier is used as an `index` into a ShaMap tree, which in ripple, is +representative of a point in time. In fact a ShaMap can be hashed +deterministically, thus a point in time can be identified by a `hash`. Where is +a ShaMap actually stored? In the NodeStore, of course. + +But the NodeStore only stores binary content you protest! But the ShaMap has a +binary representation! So what are the `contents` of a ShaMap, to be hashed to +be stored in the NodeStore? + +Glad you asked. A tree, has a root, and many children, either more branches, or +terminal leaves. The root, and any of its children that have children +themselves, are classed as `inner nodes`. + +In a ShaMap these `inner nodes` each have 16 `slots` for children. The binary +representation of these is simply 16 `hash`es, used to retrieve child nodes from +the NodeStore. + +An example of an inner node's `contents` + + Empty slots are represented as 32 0 bytes + + ``` + 022CC592F5D4ABC3A63DA2A036CDDC0825B30717C78EF287BEF200056133FDA2 + 0000000000000000000000000000000000000000000000000000000000000000 + BEE626551799DDFE65BD2D9A0F0EA24D72C93CFD8E083176718D2B079EC60214 + E1B34F1D9209CB668A50CCEE71C8109D140A6D715D923AEE98E6D53015D8B66B + 4C27A856094CFDE37CD2A0EA93DADB595B10CFEC55F816C987A6AC48D13AF5C0 + 2F770714A9EF92792F44AA1537C18F68AFE3FFF157FB9088FFE2BDA695C19B71 + C915CA982310CF41CF1266AA43C3B31ACBF4304D05ADB54A352D942C890763A3 + F29FAD442CE204513BEA555A4192E324407444D946449CEA510C37A9BB982134 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 44B3BE10744EA2DA010D530C6AE64E3C3984DA7701EE79A66EA429EC11B87D1D + 0C7BE8569E9F08BADDEB91EBE79E5B98BBF245B067B7B83B4A95430CFEC9F7E8 + BB38EA169DB6A020EA820BD1242DDB6250B397A26015507BA3C7F3C041EA683C + 0000000000000000000000000000000000000000000000000000000000000000 + 15B98934D22B5CB7233C42CE8DC8DD0D2328AB91CC574332C45D7160BD31D4AD + 1894E389AE4A63BA99C2D0546A58A976ECDAB14C09B98F532999B464696E29E5 + ``` + +What about those `index` thingies again? Remember, the `index` can't be used to +query something directly in the NodeStore. + +First you need a known point in time, which we learned could be defined by a +`hash` of a ShaMap. + +* shamap hash: 2F049AEE51C7C96AB911AF86E3278F4F90A38D196422A832617FF0C6F29C3704 +* value index: FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB + +Imagine we have those above. First we query the NodeStore with `2F049A...` + +What do we expect back? A ShaMap hash is the hash of the binary representation +of the root node (which is an `inner node`) of the tree, so we'd expect +something in the form shown earlier, with 16 256 bit hashes. + +From the NodeStore we retrieve: + + ``` + 4D494E00 + 3C926652404076CA35EA1D89580975C50DCD0B29EC16079F168BE63BB1D6F237 + F0D3F178C56C438C597D53FF5E3D44EE3865C17A0D25DCC2460F20BE4BEB4B7E + D65D6CA291E451E6D6566A5431D755A749D9B0450E83B376148A6F93349ACD46 + 309B18093008055BE23E118DA4243DFC9AEF66E3260E2008BD6E6E6806F06725 + 0000000000000000000000000000000000000000000000000000000000000000 + D7D5A7C89DAE6D7517EDCB0601829CB339376EECD1DE8CA0216B6C18FFD77C32 + 7C33AEB525B09A7BC013C01015D59A88129A8A6C18B45E6D7D0CA1F13E6FCB44 + AB35119A7529D4BA57C41D7020833A0E9600895F61E9E9DEABBFDF82A877CBB2 + 3BE7A48570263034E6DCBEFA6ED57B63C0592AE145341A79DAF57C3BDF7C5793 + 17006AD967A1536E0441517990AD5B42890A3168AC9E045EAF9AC5A06F672561 + 94B12B8BB76D525DD9320AF51893A6D69FF730C1E647181E7A7B51FE1FBF369E + 0579A72B3209AE66840F6E8317F422F43937E6AE1A14C8B30243DE016551643F + B873AA4EF1CDF0332C59BE423256610C4C6A1D32E2A1F8DE748390E29E8FC2D3 + EB03A93BBC95ED56FB73E6FBDAB8F6916BBD1BD358336CBA4DA673558F5B068C + E64A78A07CF33C3B74AEA9862B5758513677324D4C9D72C69D14B4EB64D4EB02 + 4E8C0CE75693B85A4CAC5516B77702E660A55281CF17DBE09552941F3078D81C + ``` + +We see the hashes for 16 nodes clear as day, but what is this `4D494E00` +prefixed to the front? Converted to `ascii` letters the hex `4D494E00` is +`MIN\x00`, meaning sham)ap i)nner n)ode. + +The prefix `namespaces` the content, so different classes of objects which +would otherwise have the same binary representation, will have a different +`hash`. These `hash prefixes` serve another useful purpose, as we'll see later. +(Similarly, there are namespacing prefixes for an `index` (created by + feeding static components of an identity into a hashing function)) + +Is our value `index` hash amongst those enumerated? No !!! So what do we do with +it? An index, usually means an ordinal, defining a place in an array. The +`index` is actually an index into 64 arrays. Each nibble in the `index` is an +index into the 16 slots in each inner node. + +Consider again the value `index`: + + `FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB` + +To use the `index` we take the first nibble, `F` (yes, we go left to right) + +The letter `F` in hex has the ordinal value 15, so we take the 16th branch (0 +based indexing) + +We select the 16th hash + + `4E8C0CE75693B85A4CAC5516B77702E660A55281CF17DBE09552941F3078D81C` + +From the NodeStore we retrieve: + + ``` + 4D494E00 + 0000000000000000000000000000000000000000000000000000000000000000 + 286BC64A4A369857E4B0B5834C54CED797110D06E64F7759FBA2C87D3630D418 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 60631B91674954D21314B89CEE3B7F740B4FB1374610498EA1A7A3B79BA6706D + 3B1C36A6311256FE1E72BEDBA2042D67D86F561E51B387CFA680BCE9982CD6DB + 5568E7032EE018CA484C181CD68411B623229D0666AE0038708500C59402A282 + 0000000000000000000000000000000000000000000000000000000000000000 + ``` + +There's that 'MIN\x00` hash prefix again. + +In fact, this prefix is how we can deterministically say that this is an +`inner node` and that we can interpret the following bytes as 16 more +`hash`es. + +We have descended deeper into the tree, but it seems we need to go deeper. We +are currently at a depth of 2, so to go deeper we need the 2nd nibble. + +value index: + ``` + FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB` + | + \ + 2nd nibble + ``` + +The letter `E` in hex has the ordinal value 14, so we take the 15th branch (0 +based indexing) + +We select the 15th hash: + + `5568E7032EE018CA484C181CD68411B623229D0666AE0038708500C59402A282` + +From the NodeStore we retrieve: + + ``` + 534E4400 + C11C12000722800000002400AA7BFF201900AA7BFC201B0226FF9464D4461B5C + A191A906000000000000000000000000455448000000000006CC4A6D023E68AA + 3499C6DE3E9F2DC52B8BA25465400000000861014A6840000000000000C17321 + 03CF1DFB34A96363FF2B91638FCE51E6D7B88419729E9A81ABC99A9512FFB9C7 + 3374463044022005ED4635AE246A4060378D9396CAA0E42F7E9129D309B2E98B + DF5CE2352520A002207D4494019EA4327F4087EA34B05CE9E5CD0AE3082BAD77 + CC3698CE5A59C21BD581140BEC53D0830ADCE9E372086E570809916C440E83C3 + F4201C00000033F8E311006F561BF352EEDB9072286286A4BBC8C419C995A171 + 0AA0CFA8B0D2B843F07D294F60E82400AA7BFF501090B86A84C7F7843673BCF8 + 2E565E69498CAEF463F8055ABA4C04581E76C9270064D4461B5CA191A9060000 + 00000000000000000000455448000000000006CC4A6D023E68AA3499C6DE3E9F + 2DC52B8BA25465400000000861014A81140BEC53D0830ADCE9E372086E570809 + 916C440E83E1E1E31100645690B86A84C7F7843673BCF82E565E69498CAEF463 + F8055ABA4C04581E76C92700E8364C04581E76C927005890B86A84C7F7843673 + BCF82E565E69498CAEF463F8055ABA4C04581E76C92700011100000000000000 + 00000000004554480000000000021106CC4A6D023E68AA3499C6DE3E9F2DC52B + 8BA254E1E1E41100645690B86A84C7F7843673BCF82E565E69498CAEF463F805 + 5ABA4C045835BF30CCBFE72200000000364C045835BF30CCBF5890B86A84C7F7 + 843673BCF82E565E69498CAEF463F8055ABA4C045835BF30CCBF011100000000 + 00000000000000004554480000000000021106CC4A6D023E68AA3499C6DE3E9F + 2DC52B8BA2540311000000000000000000000000000000000000000004110000 + 000000000000000000000000000000000000E1E1E411006F56AE4B62A73DC540 + 40E523FCE863981AB601B6D6BCD3CFCE303B43A430FC6D4DB1E7220000000024 + 00AA7BFC250226FF9133000000000000000034000000000000000055B61A418E + 421021CFBA22B02F4934B4F79B1091F91CF910AEB21DA0975CEC52AB501090B8 + 6A84C7F7843673BCF82E565E69498CAEF463F8055ABA4C045835BF30CCBF64D4 + 461B7D5C693EDF000000000000000000000000455448000000000006CC4A6D02 + 3E68AA3499C6DE3E9F2DC52B8BA25465400000000861014A81140BEC53D0830A + DCE9E372086E570809916C440E83E1E1E511006456B937CC88FCAF18886CC8D4 + B19A5326F56B0B84E06AE511407B072DE348E05376E722000000003100000000 + 0000000032000000000000000058B937CC88FCAF18886CC8D4B19A5326F56B0B + 84E06AE511407B072DE348E0537682140BEC53D0830ADCE9E372086E57080991 + 6C440E83E1E1E5110061250226FF915558E2CDAB1D8D5477D8FED6EA5EFD9F9F + D8FAC56EA907E94197900C6C6175CE9556E9293AF964F2B20467530673C8F327 + 41ED03DEF52F6B6625B4D837C155856C26E62400AA7BFF6240000000B60EBC57 + E1E722000000002400AA7C002D000000186240000000B60EBB9681140BEC53D0 + 830ADCE9E372086E570809916C440E83E1E1F1031000 + FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB + ``` + +Well, here's something new. The `hash prefix` is different. This time the +hex decodes as `MLN\x00`, meaning sham)ap l)eaf n)ode. + +And what's that at the end? Is that our index? It is!! + +Why does it need to be stored? We have only used `FE` to traverse to this +node. Without storing the `index` identifier in the leaf node contents, +there would be no way to be certain that this leaf held the item you wanted. +More importantly, it acts as further name-spacing, to prevent collisions. +(Technically, you could synthesize the index, by parsing the contents of +the object and recreating it) + +Takeaways +--------- + +* A `hash` keys the NodeStore +* An `index` is a path to an item in a ShaMap +* For communication purposes + - Always use `hash` when referring to a key for the NodeStore + - Always use `index` when referring to a key for a ShaMap + +Links +----- + +* [Rippled Hash Prefix declarations](../../coretypes/hash/prefixes/HashPrefix.java) \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java new file mode 100644 index 0000000000..0129eb7c4a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java @@ -0,0 +1,30 @@ +package com.ripple.core.types.shamap; + +import java.util.concurrent.atomic.AtomicInteger; + +public class ShaMap extends ShaMapInner { + private AtomicInteger copies; + + public ShaMap() { + super(0); + // This way we can copy the first to the second, + // copy the second, then copy the first again ;) + copies = new AtomicInteger(); + } + public ShaMap(boolean isCopy, int depth) { + super(isCopy, depth, 0); + } + + @Override + protected ShaMapInner makeInnerOfSameClass(int depth) { + return new ShaMap(true, depth); + } + + public ShaMap copy() { + version = copies.incrementAndGet(); + ShaMap copy = (ShaMap) copy(copies.incrementAndGet()); + copy.copies = copies; + return copy; + } + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java new file mode 100644 index 0000000000..41e23d50e1 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java @@ -0,0 +1,122 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; + +import java.util.TreeSet; + +public class ShaMapDiff { + public ShaMap one, two; + + public TreeSet modified = new TreeSet<>(); + public TreeSet deleted = new TreeSet<>(); + public TreeSet added = new TreeSet<>(); + + public ShaMapDiff(ShaMap one, ShaMap two) { + this.one = one; + this.two = two; + } + + // Find what's added, modified and deleted in `two` + public ShaMapDiff find() { + one.hash(); + two.hash(); + compare(one, two); + return this; + } + + public ShaMapDiff inverted() { + ShaMapDiff shaMapDiff = new ShaMapDiff(two, one); + + shaMapDiff.added = deleted; + shaMapDiff.modified = modified; + shaMapDiff.deleted = added; + + return shaMapDiff; + } + + public void apply(ShaMap sa) { + for (Hash256 mod : modified) { + boolean modded = sa.updateItem(mod, two.getItem(mod).copy()); + if (!modded) throw new AssertionError(); + } + + for (Hash256 add : added) { + boolean added = sa.addItem(add, two.getItem(add).copy()); + if (!added) throw new AssertionError(); + } + for (Hash256 delete : deleted) { + boolean removed = sa.removeLeaf(delete); + if (!removed) throw new AssertionError(); + } + } + private void compare(ShaMapInner a, ShaMapInner b) { + for (int i = 0; i < 16; i++) { + ShaMapNode aChild = a.getBranch(i); + ShaMapNode bChild = b.getBranch(i); + + if (aChild == null && bChild != null) { + trackAdded(bChild); + // added in B + } else if (aChild != null && bChild == null) { + trackRemoved(aChild); + // removed from B + } else if (aChild != null && !aChild.hash().equals(bChild.hash())) { + boolean aleaf = aChild.isLeaf(), + bLeaf = bChild.isLeaf(); + + if (aleaf && bLeaf) { + ShaMapLeaf la = (ShaMapLeaf) aChild; + ShaMapLeaf lb = (ShaMapLeaf) bChild; + if (la.index.equals(lb.index)) { + modified.add(la.index); + } else { + deleted.add(la.index); + added.add(lb.index); + } + } else if (aleaf /*&& bInner*/) { + ShaMapLeaf la = (ShaMapLeaf) aChild; + ShaMapInner ib = (ShaMapInner) bChild; + trackAdded(ib); + + //noinspection Duplicates + if (ib.hasLeaf(la.index)) { + // because trackAdded would have added it + added.remove(la.index); + ShaMapLeaf leaf = ib.getLeaf(la.index); + if (!leaf.hash().equals(la.hash())) { + modified.add(la.index); + } + } else { + deleted.add(la.index); + } + } else if (bLeaf /*&& aInner*/) { + ShaMapLeaf lb = (ShaMapLeaf) bChild; + ShaMapInner ia = (ShaMapInner) aChild; + trackRemoved(ia); + + //noinspection Duplicates + if (ia.hasLeaf(lb.index)) { + // because trackRemoved would have deleted it + deleted.remove(lb.index); + ShaMapLeaf leaf = ia.getLeaf(lb.index); + if (!leaf.hash().equals(lb.hash())) { + modified.add(lb.index); + } + } else { + added.add(lb.index); + } + } else /*if (aInner && bInner)*/ { + compare((ShaMapInner) aChild, (ShaMapInner) bChild); + } + } + } + } + + private void trackRemoved(ShaMapNode child) { + child.walkAnyLeaves(leaf -> deleted.add(leaf.index)); + } + + private void trackAdded(ShaMapNode child) { + child.walkAnyLeaves(leaf -> added.add(leaf.index)); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java new file mode 100644 index 0000000000..f7d73dae65 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java @@ -0,0 +1,331 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; + +import java.util.Iterator; + +public class ShaMapInner extends ShaMapNode implements Iterable { + public int depth; + int slotBits = 0; + int version = 0; + boolean doCoW; + protected ShaMapNode[] branches = new ShaMapNode[16]; + + public ShaMapInner(int depth) { + this(false, depth, 0); + } + + public ShaMapInner(boolean isCopy, int depth, int version) { + this.doCoW = isCopy; + this.depth = depth; + this.version = version; + } + + protected ShaMapInner copy(int version) { + ShaMapInner copy = makeInnerOfSameClass(depth); + System.arraycopy(branches, 0, copy.branches, 0, branches.length); + copy.slotBits = slotBits; + copy.hash = hash; + copy.version = version; + doCoW = true; + + return copy; + } + + protected ShaMapInner makeInnerOfSameClass(int depth) { + return new ShaMapInner(true, depth, version); + } + + protected ShaMapInner makeInnerChild() { + int childDepth = depth + 1; + if (childDepth >= 64) throw new AssertionError(); + return new ShaMapInner(doCoW, childDepth, version); + } + + // Descend into the tree, find the leaf matching this index + // and if the tree has it. + protected void setLeaf(ShaMapLeaf leaf) { + if (leaf.version == -1) { + leaf.version = version; + } + setBranch(leaf.index, leaf); + } + + private void removeBranch(Hash256 index) { + removeBranch(selectBranch(index)); + } + + public void walkLeaves(LeafWalker leafWalker) { + for (ShaMapNode branch : branches) { + if (branch != null) { + if (branch.isInner()) { + branch.asInner().walkLeaves(leafWalker); + } else if (branch.isLeaf()) { + leafWalker.onLeaf(branch.asLeaf()); + } + } + } + } + + public void walkTree(TreeWalker treeWalker) { + treeWalker.onInner(this); + for (ShaMapNode branch : branches) { + if (branch != null) { + if (branch.isLeaf()) { + ShaMapLeaf ln = branch.asLeaf(); + treeWalker.onLeaf(ln); + } else if (branch.isInner()) { + ShaMapInner childInner = branch.asInner(); + childInner.walkTree(treeWalker); + } + } + } + + } + + public void walkHashedTree(HashedTreeWalker walker) { + walker.onInner(hash(), this); + + for (ShaMapNode branch : branches) { + if (branch != null) { + if (branch.isLeaf()) { + ShaMapLeaf ln = branch.asLeaf(); + walker.onLeaf(branch.hash(), ln); + } else if (branch.isInner()) { + ShaMapInner childInner = branch.asInner(); + childInner.walkHashedTree(walker); + } + } + } + } + + /** + * @return the `only child` leaf or null if other children + */ + public ShaMapLeaf onlyChildLeaf() { + ShaMapLeaf leaf = null; + int leaves = 0; + + for (ShaMapNode branch : branches) { + if (branch != null) { + if (branch.isInner()) { + leaf = null; + break; + } else if (++leaves == 1) { + leaf = branch.asLeaf(); + } else { + leaf = null; + break; + } + } + } + return leaf; + } + + public boolean removeLeaf(Hash256 index) { + PathToIndex path = pathToIndex(index); + if (path.hasMatchedLeaf()) { + ShaMapInner top = path.dirtyOrCopyInners(); + top.removeBranch(index); + path.collapseOnlyLeafChildInners(); + return true; + } else { + return false; + } + } + + public ShaMapItem getItem(Hash256 index) { + ShaMapLeaf leaf = getLeaf(index); + + @SuppressWarnings("unchecked") + ShaMapItem shaMapItem = leaf == null ? null : leaf.item; + return shaMapItem; + } + + public boolean addItem(Hash256 index, ShaMapItem item) { + return addLeaf(new ShaMapLeaf(index, item)); + } + + public boolean updateItem(Hash256 index, ShaMapItem item) { + return updateLeaf(new ShaMapLeaf(index, item)); + } + + public boolean hasLeaf(Hash256 index) { + return pathToIndex(index).hasMatchedLeaf(); + } + + public ShaMapLeaf getLeaf(Hash256 index) { + PathToIndex stack = pathToIndex(index); + if (stack.hasMatchedLeaf()) { + return stack.leaf; + } else { + return null; + } + } + + public boolean addLeaf(ShaMapLeaf leaf) { + PathToIndex stack = pathToIndex(leaf.index); + if (stack.hasMatchedLeaf()) { + return false; + } else { + ShaMapInner top = stack.dirtyOrCopyInners(); + top.addLeafToTerminalInner(leaf); + return true; + } + } + + public boolean updateLeaf(ShaMapLeaf leaf) { + PathToIndex stack = pathToIndex(leaf.index); + if (stack.hasMatchedLeaf()) { + ShaMapInner top = stack.dirtyOrCopyInners(); + // Why not update in place? Because of structural sharing + top.setLeaf(leaf); + return true; + } else { + return false; + } + } + + public PathToIndex pathToIndex(Hash256 index) { + return new PathToIndex(this, index); + } + + /** + * This should only be called on the deepest inners, as it + * does not do any dirtying. + * @param leaf to add to inner + */ + void addLeafToTerminalInner(ShaMapLeaf leaf) { + ShaMapNode branch = getBranch(leaf.index); + if (branch == null) { + setLeaf(leaf); + } else if (branch.isInner()) { + // This should never be called + throw new AssertionError(); + } else if (branch.isLeaf()) { + ShaMapInner inner = makeInnerChild(); + setBranch(leaf.index, inner); + inner.addLeafToTerminalInner(leaf); + inner.addLeafToTerminalInner(branch.asLeaf()); + } + } + + protected void setBranch(Hash256 index, ShaMapNode node) { + setBranch(selectBranch(index), node); + } + + protected ShaMapNode getBranch(Hash256 index) { + return getBranch(index.nibblet(depth)); + } + + public ShaMapNode getBranch(int i) { + return branches[i]; + } + + public ShaMapNode branch(int i) { + return branches[i]; + } + + protected int selectBranch(Hash256 index) { + return index.nibblet(depth); + } + + public boolean hasLeaf(int i) { + return branches[i].isLeaf(); + } + public boolean hasInner(int i) { + return branches[i].isInner(); + } + public boolean hasNone(int i) {return branches[i] == null;} + + private void setBranch(int slot, ShaMapNode node) { + slotBits = slotBits | (1 << slot); + branches[slot] = node; + invalidate(); + } + + private void removeBranch(int slot) { + branches[slot] = null; + slotBits = slotBits & ~(1 << slot); + } + public boolean empty() { + return slotBits == 0; + } + + @Override public boolean isLeaf() { return false; } + @Override public boolean isInner() { return true; } + + @Override + Prefix hashPrefix() { + return HashPrefix.innerNode; + } + + @Override + public void toBytesSink(BytesSink sink) { + for (ShaMapNode branch : branches) { + if (branch != null) { + branch.hash().toBytesSink(sink); + } else { + Hash256.ZERO_256.toBytesSink(sink); + } + } + } + + @Override + public Hash256 hash() { + if (empty()) { + // empty inners have a hash of all ZERO + // it's only valid for a root node to be empty + // any other inner node, must contain at least a + // single leaf + assert depth == 0; + return Hash256.ZERO_256; + } else { + // hash the hashPrefix() and toBytesSink + return super.hash(); + } + } + + public ShaMapLeaf getLeafForUpdating(Hash256 leaf) { + PathToIndex path = pathToIndex(leaf); + if (path.hasMatchedLeaf()) { + return path.invalidatedPossiblyCopiedLeafForUpdating(); + } + return null; + } + + @Override + public Iterator iterator() { + return new Iterator() { + int ix = 0; + + @Override + public boolean hasNext() { + return ix != 16; + } + + @Override + public ShaMapNode next() { + return branch(ix++); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public int branchCount() { + int populated = 0; + for (ShaMapNode branch : branches) { + if (branch != null) { + populated ++; + } + } + return populated; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java new file mode 100644 index 0000000000..a8ec303dbb --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java @@ -0,0 +1,11 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; + +abstract public class ShaMapItem { + abstract void toBytesSink(BytesSink sink); + public abstract ShaMapItem copy(); + public abstract T value(); + public abstract Prefix hashPrefix(); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java new file mode 100644 index 0000000000..3a79dacb94 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java @@ -0,0 +1,34 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; + +public class ShaMapLeaf extends ShaMapNode { + public Hash256 index; + public ShaMapItem item; + public long version = -1; + + protected ShaMapLeaf(Hash256 index, ShaMapItem item) { + this.index = index; + this.item = item; + } + + @Override public boolean isLeaf() {return true;} + @Override public boolean isInner() {return false;} + + @Override + Prefix hashPrefix() { + return item.hashPrefix(); + } + + @Override + public void toBytesSink(BytesSink sink) { + item.toBytesSink(sink); + index.toBytesSink(sink); + } + + public ShaMapLeaf copy() { + return new ShaMapLeaf(index, item.copy()); + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java new file mode 100644 index 0000000000..c5e6d00aca --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java @@ -0,0 +1,47 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.HalfSha512; +import com.ripple.core.coretypes.hash.Hash256; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BytesSink; + +abstract public class ShaMapNode { + protected Hash256 hash; + + // This saves a lot of instanceof checks + public abstract boolean isLeaf(); + public abstract boolean isInner(); + + public ShaMapLeaf asLeaf() { + return (ShaMapLeaf) this; + } + public ShaMapInner asInner() { + return (ShaMapInner) this; + } + + abstract Prefix hashPrefix(); + abstract public void toBytesSink(BytesSink sink); + + public void invalidate() {hash = null;} + public Hash256 hash() { + if (hash == null) { + hash = createHash(); + } + return hash; + } + private Hash256 createHash() { + HalfSha512 half = HalfSha512.prefixed256(hashPrefix()); + toBytesSink(half); + return half.finish(); + } + /** + * Walk any leaves, possibly this node itself, if it's terminal. + */ + public void walkAnyLeaves(LeafWalker leafWalker) { + if (isLeaf()) { + leafWalker.onLeaf(asLeaf()); + } else { + asInner().walkLeaves(leafWalker); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java new file mode 100644 index 0000000000..9e4d34a39d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java @@ -0,0 +1,38 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.coretypes.hash.prefixes.HashPrefix; +import com.ripple.core.coretypes.hash.prefixes.Prefix; +import com.ripple.core.serialized.BinarySerializer; +import com.ripple.core.serialized.BytesSink; +import com.ripple.core.types.known.tx.result.TransactionResult; + +public class TransactionResultItem extends ShaMapItem { + public TransactionResult result; + + public TransactionResultItem(TransactionResult result) { + this.result = result; + } + + @Override + void toBytesSink(BytesSink sink) { + BinarySerializer write = new BinarySerializer(sink); + write.addLengthEncoded(result.txn); + write.addLengthEncoded(result.meta); + } + + @Override + public ShaMapItem copy() { + // that's ok right ;) these bad boys are immutable anyway + return this; + } + + @Override + public TransactionResult value() { + return result; + } + + @Override + public Prefix hashPrefix() { + return HashPrefix.txNode; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java new file mode 100644 index 0000000000..3993b3795d --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java @@ -0,0 +1,6 @@ +package com.ripple.core.types.shamap; +import com.ripple.core.types.known.tx.result.TransactionResult; + +public interface TransactionResultVisitor { + public void onTransaction(TransactionResult tx); +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java new file mode 100644 index 0000000000..72c4ac4ddc --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java @@ -0,0 +1,43 @@ +package com.ripple.core.types.shamap; + +import com.ripple.core.types.known.tx.result.TransactionResult; + +import java.util.TreeSet; + +public class TransactionTree extends ShaMap { + public TransactionTree() { + super(); + } + + public TransactionTree(boolean isCopy, int depth) { + super(isCopy, depth); + } + + @Override + protected ShaMapInner makeInnerOfSameClass(int depth) { + return new TransactionTree(true, depth); + } + + public void addTransactionResult(TransactionResult tr) { + TransactionResultItem item = new TransactionResultItem(tr); + addItem(tr.hash, item); + } + + @Override + public TransactionTree copy() { + return (TransactionTree) super.copy(); + } + + public void walkTransactions(final TransactionResultVisitor walker) { + walkLeaves(leaf -> { + TransactionResultItem item = (TransactionResultItem) leaf.item; + walker.onTransaction(item.result); + }); + } + + public TreeSet toTreeSet() { + TreeSet result = new TreeSet<>(); + walkTransactions(result::add); + return result; + } +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java new file mode 100644 index 0000000000..de225e9eaf --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java @@ -0,0 +1,6 @@ +package com.ripple.core.types.shamap; + +public interface TreeWalker { + public void onLeaf(ShaMapLeaf leaf); + public void onInner(ShaMapInner inner); +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/Seed.java b/ripple-core/src/main/java/com/ripple/crypto/Seed.java new file mode 100644 index 0000000000..5c0231828f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/Seed.java @@ -0,0 +1,85 @@ +package com.ripple.crypto; + +import com.ripple.crypto.ecdsa.K256; +import com.ripple.crypto.ed25519.EDKeyPair; +import com.ripple.crypto.keys.IKeyPair; +import com.ripple.encodings.addresses.Addresses; +import com.ripple.encodings.base58.B58; +import com.ripple.utils.Sha512; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +public class Seed { + private final byte[] seedBytes; + private B58.Version version; + + public Seed(byte[] seedBytes) { + this(Addresses.SEED_K256, seedBytes); + } + + public Seed(B58.Version version, byte[] seedBytes) { + this.seedBytes = seedBytes; + this.version = version; + } + + @Override + public String toString() { + return Addresses.encode(seedBytes, version); + } + + public byte[] bytes() { + return seedBytes; + } + + public B58.Version version() { + return version; + } + + public Seed setEd25519() { + this.version = Addresses.SEED_ED25519; + return this; + } + + public IKeyPair keyPair() { + return keyPair(0); + } + + public IKeyPair rootKeyPair() { + return keyPair(-1); + } + + public IKeyPair keyPair(int account) { + if (version == Addresses.SEED_ED25519 || + Arrays.equals(version.bytes, Addresses.SEED_ED25519.bytes)) { + if (account != 0) throw new IllegalStateException(); + return EDKeyPair.from128Seed(seedBytes); + } else { + return K256.createKeyPair(seedBytes, account); + } + + } + + public static Seed fromBase58(String b58) { + B58.Decoded decoded = Addresses.decodeSeed(b58); + return new Seed(decoded.version, decoded.payload); + } + + public static Seed fromPassPhrase(String passPhrase) { + return new Seed(passPhraseToSeedBytes(passPhrase)); + } + + public static byte[] passPhraseToSeedBytes(String phrase) { + try { + return new Sha512(phrase.getBytes("utf-8")).finish128(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static IKeyPair getKeyPair(String b58) { + return fromBase58(b58).keyPair(); + } +} + + diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java new file mode 100644 index 0000000000..ab61bfec30 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java @@ -0,0 +1,155 @@ +package com.ripple.crypto.ecdsa; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.DERSequenceGenerator; +import org.bouncycastle.asn1.DLSequence; +import org.bouncycastle.crypto.signers.ECDSASigner; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; + +public class ECDSASignature { + /** The two components of the signature. */ + public BigInteger r, s; + + /** Constructs a signature with the given components. */ + public ECDSASignature(BigInteger r, BigInteger s) { + this.r = r; + this.s = s; + } + + public static boolean isStrictlyCanonical(byte[] sig) { + return checkIsCanonical(sig, true); + } + + public static boolean checkIsCanonical(byte[] sig, boolean strict) { + // Make sure signature is canonical + // To protect against signature morphing attacks + + // Signature should be: + // <30> [ <02> ] [ <02> ] + // where + // 6 <= len <= 70 + // 1 <= lenR <= 33 + // 1 <= lenS <= 33 + + int sigLen = sig.length; + + if ((sigLen < 8) || (sigLen > 72)) + return false; + + if ((sig[0] != 0x30) || (sig[1] != (sigLen - 2))) + return false; + + // Find R and check its length + int rPos = 4, rLen = sig[rPos - 1]; + + if ((rLen < 1) || (rLen > 33) || ((rLen + 7) > sigLen)) + return false; + + // Find S and check its length + int sPos = rLen + 6, sLen = sig[sPos - 1]; + if ((sLen < 1) || (sLen > 33) || ((rLen + sLen + 6) != sigLen)) + return false; + + if ((sig[rPos - 2] != 0x02) || (sig[sPos - 2] != 0x02)) + return false; // R or S have wrong type + + if ((sig[rPos] & 0x80) != 0) + return false; // R is negative + + if ((sig[rPos] == 0) && rLen == 1) + return false; // R is zero + + if ((sig[rPos] == 0) && ((sig[rPos + 1] & 0x80) == 0)) + return false; // R is padded + + if ((sig[sPos] & 0x80) != 0) + return false; // S is negative + + if ((sig[sPos] == 0) && sLen == 1) + return false; // S is zero + + if ((sig[sPos] == 0) && ((sig[sPos + 1] & 0x80) == 0)) + return false; // S is padded + + + byte[] rBytes = new byte[rLen]; + byte[] sBytes = new byte[sLen]; + + System.arraycopy(sig, rPos, rBytes, 0, rLen); + System.arraycopy(sig, sPos, sBytes, 0, sLen); + + BigInteger r = new BigInteger(1, rBytes), s = new BigInteger(1, sBytes); + + BigInteger order = SECP256K1.order(); + + if (r.compareTo(order) != -1 || s.compareTo(order) != -1) { + return false; // R or S greater than modulus + } + if (strict) { + return order.subtract(s).compareTo(s) != -1; + } else { + return true; + } + + } + + public static ECDSASignature createSignature(byte[] hash, ECDSASigner signer) { + BigInteger[] sigs = signer.generateSignature(hash); + BigInteger r = sigs[0], s = sigs[1]; + + BigInteger otherS = SECP256K1.order().subtract(s); + if (s.compareTo(otherS) > 0) { + s = otherS; + } + + return new ECDSASignature(r, s); + } + + /** + * DER is an international standard for serializing data structures which is widely used in cryptography. + * It's somewhat like protocol buffers but less convenient. This method returns a standard DER encoding + * of the signature, as recognized by OpenSSL and other libraries. + */ + public byte[] encodeToDER() { + try { + return derByteStream().toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); // Cannot happen. + } + } + + public static ECDSASignature decodeFromDER(byte[] bytes) { + try { + ASN1InputStream decoder = new ASN1InputStream(bytes); + DLSequence seq = (DLSequence) decoder.readObject(); + ASN1Integer r, s; + try { + r = (ASN1Integer) seq.getObjectAt(0); + s = (ASN1Integer) seq.getObjectAt(1); + } catch (ClassCastException e) { + return null; + } finally { + decoder.close(); + } + // OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be + // Thus, we always use the positive versions. See: http://r6.ca/blog/20111119T211504Z.html + return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected ByteArrayOutputStream derByteStream() throws IOException { + // Usually 70-72 bytes. + ByteArrayOutputStream bos = new ByteArrayOutputStream(72); + DERSequenceGenerator seq = new DERSequenceGenerator(bos); + seq.addObject(new ASN1Integer(r)); + seq.addObject(new ASN1Integer(s)); + seq.close(); + return bos; + } +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java new file mode 100644 index 0000000000..1f93f23465 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java @@ -0,0 +1,103 @@ +package com.ripple.crypto.ecdsa; + +import com.ripple.utils.Sha512; +import com.ripple.utils.Utils; +import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; + +public class K256 { + + /** + * @param secretKey secret point on the curve as BigInteger + * @return corresponding public point + */ + public static byte[] getPublic(BigInteger secretKey) { + return SECP256K1.basePointMultipliedBy(secretKey); + } + + /** + * @param secretKey secret point on the curve as BigInteger + * @return corresponding public point + */ + private static ECPoint computePublic(BigInteger secretKey) { + return SECP256K1.basePoint().multiply(secretKey); + } + + /** + * @param privateGen secret point on the curve as BigInteger + * @return the corresponding public key is the public generator + * (aka public root key, master public key). + * return as byte[] for convenience. + */ + private static ECPoint computePublicGenerator(BigInteger privateGen) { + return computePublic(privateGen); + } + + private static BigInteger computePrivateGen(byte[] seedBytes) { + return generateKey(seedBytes, null); + } + + public static byte[] computePublicKey(byte[] publicGenBytes, + int accountNumber) { + ECPoint rootPubPoint = SECP256K1.curve().decodePoint(publicGenBytes); + BigInteger scalar = generateKey(publicGenBytes, accountNumber); + ECPoint point = SECP256K1.basePoint().multiply(scalar); + ECPoint offset = rootPubPoint.add(point); + return offset.getEncoded(true); + } + + private static BigInteger computeSecretKey(BigInteger privateGen, + byte[] publicGenBytes, + int accountNumber) { + return generateKey(publicGenBytes, accountNumber) + .add(privateGen).mod(SECP256K1.order()); + } + + /** + * @param seedBytes - a bytes sequence of arbitrary length which will be hashed + * @param discriminator - nullable optional uint32 to hash + * @return a number between [1, order -1] suitable as a private key + */ + private static BigInteger generateKey(byte[] seedBytes, Integer discriminator) { + BigInteger key = null; + for (long i = 0; i <= 0xFFFFFFFFL; i++) { + Sha512 sha512 = new Sha512().add(seedBytes); + if (discriminator != null) { + sha512.addU32(discriminator); + } + sha512.addU32((int) i); + byte[] keyBytes = sha512.finish256(); + key = Utils.uBigInt(keyBytes); + if (key.compareTo(BigInteger.ZERO) > 0 && + key.compareTo(SECP256K1.order()) < 0) { + break; + } + } + return key; + } + + static ECDSASignature createECDSASignature(byte[] hash, ECDSASigner signer) { + return ECDSASignature.createSignature(hash, signer); + } + + public static K256KeyPair createKeyPair(byte[] seedBytes, int accountNumber) { + @SuppressWarnings("SpellCheckingInspection") + BigInteger priv; + BigInteger privateGen; + // The private generator (aka root private key, master private key) + privateGen = computePrivateGen(seedBytes); + ECPoint publicGen = computePublicGenerator(privateGen); + byte[] pubGenBytes = publicGen.getEncoded(true); + + if (accountNumber == -1) { + // The root keyPair + return new K256KeyPair(privateGen, publicGen, pubGenBytes); + } else { + priv = computeSecretKey(privateGen, pubGenBytes, accountNumber); + ECPoint pub = computePublic(priv); + return new K256KeyPair(priv, pub, null); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java new file mode 100644 index 0000000000..e417c9d85c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java @@ -0,0 +1,54 @@ +package com.ripple.crypto.ecdsa; + +import com.ripple.crypto.keys.IKeyPair; +import com.ripple.utils.HashUtils; +import com.ripple.utils.Utils; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.crypto.signers.HMacDSAKCalculator; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; + +public class K256KeyPair extends K256VerifyingKey implements IKeyPair { + private byte[] privateKey; + private ECPrivateKeyParameters privateKeyParameters; + + K256KeyPair(BigInteger privateKey, ECPoint pub, byte[] pubEncoded) { + super(pub, pubEncoded); + this.privateKey = Utils.padTo256(privateKey.toByteArray()); + privateKeyParameters = new ECPrivateKeyParameters(privateKey, + SECP256K1.params()); + } + + @Override + public byte[] privateKey() { + return privateKey; + } + + @Override + public byte[] signMessage(byte[] message) { + byte[] hash = HashUtils.halfSha512(message); + return signHash(hash); + } + + public byte[] signHash(byte[] bytes) { + ECDSASigner signer = newSigner(); + + ECDSASignature sig = K256.createECDSASignature(bytes, signer); + byte[] der = sig.encodeToDER(); + if (!ECDSASignature.isStrictlyCanonical(der)) { + throw new IllegalStateException("Signature is not strictly canonical"); + } + return der; + } + + private ECDSASigner newSigner() { + ECDSASigner signer = new ECDSASigner( + new HMacDSAKCalculator(new SHA256Digest())); + signer.init(true, privateKeyParameters); + return signer; + } + +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java new file mode 100644 index 0000000000..7681c12ef6 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java @@ -0,0 +1,55 @@ +package com.ripple.crypto.ecdsa; + +import com.ripple.crypto.keys.IVerifyingKey; +import com.ripple.encodings.addresses.Addresses; +import com.ripple.utils.HashUtils; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.math.ec.ECPoint; + +public class K256VerifyingKey implements IVerifyingKey { + private final ECPublicKeyParameters keyParameters; + private final byte[] canonicalPublicKey; + + K256VerifyingKey(ECPoint publicKey, byte[] publicKeyBytes) { + if (publicKeyBytes == null) { + publicKeyBytes = publicKey.getEncoded(true); + } else if (publicKey == null) { + publicKey = SECP256K1.curve().decodePoint(publicKeyBytes); + } + canonicalPublicKey = publicKeyBytes; + keyParameters = new ECPublicKeyParameters( + publicKey, SECP256K1.params()); + } + + private K256VerifyingKey(byte[] pubKeyBytes) { + this(null, pubKeyBytes); + } + + @Override + public byte[] canonicalPubBytes() { + return canonicalPublicKey; + } + + @Override + public boolean verify(byte[] message, byte[] signature) { + byte[] bytes = HashUtils.halfSha512(message); + return verifyHash(bytes, signature); + } + + public boolean verifyHash(byte[] hash, byte[] signature) { + ECDSASigner signer = new ECDSASigner(); + signer.init(false, keyParameters); + ECDSASignature sig = ECDSASignature.decodeFromDER(signature); + return sig != null && signer.verifySignature(hash, sig.r, sig.s); + } + + public static K256VerifyingKey fromNodePublicKey(String node) { + byte[] pub = Addresses.decodeNodePublic(node); + return new K256VerifyingKey(pub); + } + + public static K256VerifyingKey fromCanonicalPubBytes(byte[] bytes) { + return new K256VerifyingKey(bytes); + } +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java new file mode 100644 index 0000000000..5350a27f75 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java @@ -0,0 +1,42 @@ +package com.ripple.crypto.ecdsa; + +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; + +public class SECP256K1 { + private static final ECDomainParameters ecParams; + private static final X9ECParameters params; + + static { + + params = SECNamedCurves.getByName("secp256k1"); + ecParams = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + } + + public static ECDomainParameters params() { + return ecParams; + } + + public static BigInteger order() { + return ecParams.getN(); + } + + + public static ECCurve curve() { + return ecParams.getCurve(); + } + + public static ECPoint basePoint() { + return ecParams.getG(); + } + + static byte[] basePointMultipliedBy(BigInteger secret) { + return basePoint().multiply(secret).getEncoded(true); + } + +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java new file mode 100644 index 0000000000..71da658b0c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java @@ -0,0 +1,9 @@ +package com.ripple.crypto.ed25519; + +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec; +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; + +public class ED25519 { + static final EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable + .getByName("Ed25519"); +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java new file mode 100644 index 0000000000..5d638617c3 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java @@ -0,0 +1,52 @@ +package com.ripple.crypto.ed25519; + +import com.ripple.crypto.keys.IKeyPair; +import com.ripple.utils.HashUtils; +import com.ripple.utils.Utils; +import net.i2p.crypto.eddsa.EdDSAEngine; +import net.i2p.crypto.eddsa.EdDSAPrivateKey; +import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +import java.math.BigInteger; +import java.security.PrivateKey; + +public class EDKeyPair extends EDVerifyingKey implements IKeyPair { + + private final EdDSAPrivateKeySpec keySpec; + + private EDKeyPair(EdDSAPrivateKeySpec keySpec) { + super(new EdDSAPublicKeySpec(keySpec.getA(), ED25519.ed25519), null); + this.keySpec = keySpec; + } + + public static EDKeyPair from256Seed(byte[] seedBytes) { + EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seedBytes, + ED25519.ed25519); + return new EDKeyPair(keySpec); + } + + public static EDKeyPair from128Seed(byte[] seedBytes) { + assert seedBytes.length == 16; + return from256Seed(HashUtils.halfSha512(seedBytes)); + } + + @Override + public byte[] privateKey() { + return keySpec.geta(); + } + + @Override + public byte[] signMessage(byte[] message) { + try { + EdDSAEngine sgr = new EdDSAEngine(sha512digest()); + PrivateKey sKey = new EdDSAPrivateKey(keySpec); + sgr.initSign(sKey); + sgr.update(message); + return sgr.sign(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java new file mode 100644 index 0000000000..e0c9da8d07 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java @@ -0,0 +1,58 @@ +package com.ripple.crypto.ed25519; + +import com.ripple.crypto.keys.IVerifyingKey; +import net.i2p.crypto.eddsa.EdDSAEngine; +import net.i2p.crypto.eddsa.EdDSAPublicKey; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; +import org.bouncycastle.util.Arrays; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class EDVerifyingKey implements IVerifyingKey { + private final EdDSAPublicKey publicKey; + private final byte[] canonicalPubBytes; + @SuppressWarnings("FieldCanBeLocal") + private final byte[] ED_PREFIX = {(byte) 0xED}; + + EDVerifyingKey(EdDSAPublicKeySpec spec, byte[] pubBytes) { + if (pubBytes == null) { + pubBytes = spec.getA().toByteArray(); + } else if (spec == null) { + spec = new EdDSAPublicKeySpec(pubBytes, ED25519.ed25519); + } + publicKey = new EdDSAPublicKey(spec); + canonicalPubBytes = Arrays.concatenate(ED_PREFIX, pubBytes); + } + + MessageDigest sha512digest() { + try { + return MessageDigest.getInstance("SHA-512"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + @Override + public byte[] canonicalPubBytes() { + return canonicalPubBytes; + } + + @Override + public boolean verify(byte[] message, byte[] sigBytes) { + try { + EdDSAEngine sgr = new EdDSAEngine(sha512digest()); + sgr.initVerify(publicKey); + sgr.update(message); + return sgr.verify(sigBytes); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static EDVerifyingKey fromCanonicalPubBytes(byte[] bytes) { + // Strip the 0xED prefix from the key + byte[] pubBytes = Arrays.copyOfRange(bytes, 1, bytes.length); + return new EDVerifyingKey(null, pubBytes); + } +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java new file mode 100644 index 0000000000..ab76848154 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java @@ -0,0 +1,6 @@ +package com.ripple.crypto.keys; + +public interface IKeyPair extends IVerifyingKey { + byte[] privateKey(); + byte[] signMessage(byte[] message); +} diff --git a/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java new file mode 100644 index 0000000000..1b1c6ed7d0 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java @@ -0,0 +1,29 @@ +package com.ripple.crypto.keys; + + +import com.ripple.crypto.ecdsa.K256VerifyingKey; +import com.ripple.crypto.ed25519.EDVerifyingKey; +import com.ripple.encodings.common.B16; +import com.ripple.utils.HashUtils; + +public interface IVerifyingKey { + default String canonicalPubHex() { + return B16.encode(canonicalPubBytes()); + } + + default byte[] id() { + return HashUtils.SHA256_RIPEMD160(canonicalPubBytes()); + } + + byte[] canonicalPubBytes(); + + boolean verify(byte[] message, byte[] sigBytes); + + static IVerifyingKey from(byte[] bytes) { + if (bytes[0] == (byte) 0xED) { + return EDVerifyingKey.fromCanonicalPubBytes(bytes); + } else { + return K256VerifyingKey.fromCanonicalPubBytes(bytes); + } + } +} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java b/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java new file mode 100644 index 0000000000..5d8022a9b6 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java @@ -0,0 +1,77 @@ +package com.ripple.encodings.addresses; + + +import com.ripple.encodings.base58.B58; +import com.ripple.encodings.basex.EncodingFormatException; +import com.ripple.encodings.basex.IBaseX; +import org.omg.IOP.Encoding; + +public class Addresses { + public static final B58 codec = new B58("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); + + // Otherwise known as `family seed` + public static final B58.Version SEED_K256 = new B58.Version( + 33, "seedK256", 16); + + public static final B58.Version SEED_ED25519 = new B58.Version( + "01E14B", "seedEd25519", 16); + + public static final B58.Version ACCOUNT_ID = new B58.Version( + 0, "accountId", 20); + + public static final B58.Version NODE_PUBLIC_KEY = new B58.Version( + 28, "nodePublicKey", 33); + + public static final B58.Version NODE_PRIVATE_KEY = new B58.Version( + 33, "nodePrivateKey", 32); + + public static byte[] decode(String encoded, B58.Version version) { + return codec.decodeVersioned(encoded, version).payload; + } + + public static String encode(byte[] bytes, B58.Version version) { + return codec.encodeVersioned(bytes, version); + } + + public static byte[] decodeSeedToBytes(String seed) { + return codec.decodeVersioned(seed, SEED_K256, SEED_ED25519) + .payload; + } + + public static B58.Decoded decodeSeed(String seed) { + return codec.decodeVersioned(seed, SEED_K256, SEED_ED25519); + } + + public static String encodeSeedK256(byte[] bytes) { + return encode(bytes, SEED_K256); + } + + public static String encodeAccountID(byte[] bytes) { + return encode(bytes, ACCOUNT_ID); + } + + public static byte[] decodeAccountID(String id) { + return decode(id, ACCOUNT_ID); + } + + public static String encodeNodePublic(byte[] bytes) { + return encode(bytes, NODE_PUBLIC_KEY); + } + + public static byte[] decodeNodePublic(String base58) { + return decode(base58, NODE_PUBLIC_KEY); + } + + public static boolean isValid(String encoded, B58.Version... versions) { + try { + codec.decodeVersioned(encoded, versions); + return true; + } catch (EncodingFormatException e) { + return false; + } + } + + public static boolean isValidAccountID(String encoded) { + return isValid(encoded, ACCOUNT_ID); + } +} diff --git a/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java b/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java new file mode 100644 index 0000000000..a6b928824e --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java @@ -0,0 +1,9 @@ +package com.ripple.encodings.base58; + +import com.ripple.encodings.basex.BaseX; + +public class B58 extends BaseX { + public B58(String alphabet) { + super(alphabet); + } +} diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java b/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java new file mode 100644 index 0000000000..4ebbfc871a --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java @@ -0,0 +1,231 @@ +package com.ripple.encodings.basex; + +import com.ripple.utils.HashUtils; + +import java.util.Arrays; + +public class BaseX implements IBaseX { + private char[] alphabet; + private final char encodedZero; + protected final int[] indexes; + + public BaseX(String alphabet_) { + if (alphabet_.length() > 256) { + throw new IllegalArgumentException(); + } + alphabet = alphabet_.toCharArray(); + indexes = new int[128]; + encodedZero = alphabet[0]; + Arrays.fill(indexes, -1); + for (int i = 0; i < alphabet.length; i++) { + indexes[alphabet[i]] = i; + } + } + + private static String repeat(int times, char repeated) { + char[] chars = new char[times]; + Arrays.fill(chars, repeated); + return new String(chars); + } + + /** + * Encodes the given bytes as a base58 string (no checksum is appended). + * + * @param input the bytes to encode + * @return the base58-encoded string + */ + @Override + public String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input.length && input[zeros] == 0) { + ++zeros; + } + // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) + input = Arrays.copyOf(input, input.length); // since we modify it in-place + char[] encoded = new char[input.length * 2]; // upper bound + int outputStart = encoded.length; + for (int inputStart = zeros; inputStart < input.length; ) { + encoded[--outputStart] = alphabet[divmod(input, inputStart, 256, 58)]; + if (input[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. + while (outputStart < encoded.length && encoded[outputStart] == encodedZero) { + ++outputStart; + } + while (--zeros >= 0) { + encoded[--outputStart] = encodedZero; + } + // Return encoded string (including encoded leading zeros). + return new String(encoded, outputStart, encoded.length - outputStart); + } + + /** + * Decodes the given base58 string into the original data bytes. + * + * @param input the base58-encoded string to decode + * @return the decoded data bytes + * @throws EncodingFormatException if the given string is not a valid base58 string + */ + @Override + public byte[] decode(String input) throws EncodingFormatException { + if (input.length() == 0) { + return new byte[0]; + } + // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). + byte[] input58 = new byte[input.length()]; + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + int digit = c < 128 ? indexes[c] : -1; + if (digit < 0) { + throw new EncodingFormatException("Illegal character " + c + " at position " + i); + } + input58[i] = (byte) digit; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input58.length && input58[zeros] == 0) { + ++zeros; + } + // Convert base-58 digits to base-256 digits. + byte[] decoded = new byte[input.length()]; + int outputStart = decoded.length; + for (int inputStart = zeros; inputStart < input58.length; ) { + decoded[--outputStart] = divmod(input58, inputStart, 58, 256); + if (input58[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Ignore extra leading zeroes that were added during the calculation. + while (outputStart < decoded.length && decoded[outputStart] == 0) { + ++outputStart; + } + // Return decoded data (including original number of leading zeros). + return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); + } + + /** + * Decodes the given base58 string into the original data bytes, using the checksum in the + * last 4 bytes of the decoded data to verify that the rest are correct. The checksum is + * removed from the returned data. + * + * @param input the base58-encoded string to decode (which should include the checksum) + * @throws EncodingFormatException if the input is not base 58 or the checksum does not validate. + */ + public byte[] decodeChecked(String input) throws EncodingFormatException { + byte[] decoded = decode(input); + if (decoded.length < 4) + throw new EncodingFormatException("Input too short"); + byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4); + byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length); + byte[] actualChecksum = Arrays.copyOfRange(HashUtils.doubleDigest(data), 0, 4); + if (!Arrays.equals(checksum, actualChecksum)) + throw new EncodingFormatException("Checksum does not validate"); + return data; + } + + /** + * Divides a number, represented as an array of bytes each containing a single digit + * in the specified base, by the given divisor. The given number is modified in-place + * to contain the quotient, and the return value is the remainder. + * + * @param number the number to divide + * @param firstDigit the index within the array of the first non-zero digit + * (this is used for optimization by skipping the leading zeros) + * @param base the base in which the number's digits are represented (up to 256) + * @param divisor the number to divide by (up to 256) + * @return the remainder of the division operation + */ + private byte divmod(byte[] number, int firstDigit, int base, int divisor) { + // this is just long division which accounts for the base of the input digits + int remainder = 0; + for (int i = firstDigit; i < number.length; i++) { + int digit = (int) number[i] & 0xFF; + int temp = remainder * base + digit; + number[i] = (byte) (temp / divisor); + remainder = temp % divisor; + } + return (byte) remainder; + } + + @Override + public byte[] findPrefix(int payLoadLength, String desiredPrefix) { + if (alphabet.length != 58) { + throw new IllegalStateException("Must be base58"); + } + int totalLength = payLoadLength + 4; // for the checksum + double chars = Math.log(Math.pow(256, totalLength)) / Math.log(58); + int requiredChars = (int) Math.ceil(chars + 0.2D); + // Mess with this to see stability tests fail + int charPos = (alphabet.length / 2) - 1; + char padding = alphabet[(charPos)]; + String template = desiredPrefix + repeat(requiredChars, padding); + byte[] decoded = decode(template); + return copyOfRange(decoded, 0, decoded.length - totalLength); + } + + @Override + public String encodeVersioned(byte[] input, Version version) { + if (input.length != version.expectedLength) { + throw new IllegalArgumentException( + "input length=" + input.length + + ", expected=" + version.expectedLength); + } + return encode(concatVersionAndAddChecksum(input, version.bytes)); + } + + private byte[] concatVersionAndAddChecksum(byte[] input, byte[] version) { + byte[] buffer = new byte[input.length + version.length]; + System.arraycopy(version, 0, buffer, 0, version.length); + System.arraycopy(input, 0, buffer, version.length, input.length); + byte[] checkSum = copyOfRange(HashUtils.doubleDigest(buffer), 0, 4); + byte[] output = new byte[buffer.length + checkSum.length]; + System.arraycopy(buffer, 0, output, 0, buffer.length); + System.arraycopy(checkSum, 0, output, buffer.length, checkSum.length); + return output; + } + + public Decoded decodeVersioned(String input, + Version... possibleVersions) throws EncodingFormatException { + + byte[] buffer = decodeChecked(input); + + Version foundVersion = null; + int expectedLength = possibleVersions[0].expectedLength; + int versionLength = buffer.length - expectedLength; + byte[] versionBytes = copyOfRange(buffer, 0, versionLength); + + for (Version possible : possibleVersions) { + if (possible.expectedLength != expectedLength) { + throw new IllegalStateException(); + } + + if (Arrays.equals(possible.bytes, versionBytes)) { + foundVersion = possible; + break; + } + } + if (foundVersion == null) { + throw new EncodingFormatException("Incorrect version"); + } + + byte[] bytes = copyOfRange(buffer, versionLength, buffer.length); + if (bytes.length != expectedLength) { + throw new EncodingFormatException("Incorrect length"); + } + + return new Decoded(foundVersion, bytes); + } + + private byte[] copyOfRange(byte[] source, int from, int to) { + byte[] range = new byte[to - from]; + System.arraycopy(source, from, range, 0, range.length); + return range; + } + +} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java b/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java new file mode 100644 index 0000000000..4c56ffa1e9 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java @@ -0,0 +1,7 @@ +package com.ripple.encodings.basex; + +public class EncodingFormatException extends RuntimeException{ + public EncodingFormatException(String message) { + super(message); + } +} diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java b/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java new file mode 100644 index 0000000000..84d98aa51b --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java @@ -0,0 +1,41 @@ +package com.ripple.encodings.basex; + +import com.ripple.encodings.common.B16; + +public interface IBaseX { + String encode(byte[] input); + byte[] decode(String input); + + byte[] findPrefix(int payLoadLength, String desiredPrefix); + + String encodeVersioned(byte[] input, Version version); + Decoded decodeVersioned(String input, Version... possibleVersions); + + class Decoded { + public final Version version; + public final byte[] payload; + + Decoded(Version version, byte[] payload) { + this.version = version; + this.payload = payload; + } + } + + class Version { + public final byte[] bytes; + public final String name; + public final int expectedLength; + + public Version(byte[] bytes, String name, int length) { + this.bytes = bytes; + this.name = name; + this.expectedLength = length; + } + public Version(int aByte, String name, int length) { + this(new byte[]{(byte) aByte}, name, length); + } + public Version(String hex, String name, int length) { + this(B16.decode(hex), name, length); + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/encodings/common/B16.java b/ripple-core/src/main/java/com/ripple/encodings/common/B16.java new file mode 100644 index 0000000000..9ab895721c --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/common/B16.java @@ -0,0 +1,20 @@ +package com.ripple.encodings.common; + + +import static org.bouncycastle.util.encoders.Hex.toHexString; + +public class B16 { + public static String toStringTrimmed(byte[] bytes) { + int offset = 0; + if (bytes[0] == 0) { + offset = 1; + } + return toHexString(bytes, offset, bytes.length - offset).toUpperCase(); + } + public static String encode(byte[] bytes) { + return toHexString(bytes).toUpperCase(); + } + public static byte[] decode(String hex) { + return org.bouncycastle.util.encoders.Hex.decode(hex); + } +} diff --git a/ripple-core/src/main/java/com/ripple/encodings/common/B64.java b/ripple-core/src/main/java/com/ripple/encodings/common/B64.java new file mode 100644 index 0000000000..e48b7d1a70 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/encodings/common/B64.java @@ -0,0 +1,12 @@ +package com.ripple.encodings.common; + +import org.bouncycastle.util.encoders.Base64; + +public class B64 { + public static String toString(byte[] bytes) { + return Base64.toBase64String(bytes); + } + public static byte[] decode(String string) { + return Base64.decode(string); + } +} diff --git a/ripple-core/src/main/java/com/ripple/utils/HashUtils.java b/ripple-core/src/main/java/com/ripple/utils/HashUtils.java new file mode 100644 index 0000000000..2d79986957 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/utils/HashUtils.java @@ -0,0 +1,62 @@ +package com.ripple.utils; + +import org.bouncycastle.crypto.digests.RIPEMD160Digest; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HashUtils { + private static final MessageDigest digest; + static { + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); // Can't happen. + } + } + + /** + * See {@link HashUtils#doubleDigest(byte[], int, int)}. + */ + public static byte[] doubleDigest(byte[] input) { + return doubleDigest(input, 0, input.length); + } + + /** + * Calculates the SHA-256 hash of the given byte range, and then hashes the resulting hash again. This is + * standard procedure in Bitcoin. The resulting hash is in big endian form. + */ + public static byte[] doubleDigest(byte[] input, int offset, int length) { + synchronized (digest) { + digest.reset(); + digest.update(input, offset, length); + byte[] first = digest.digest(); + return digest.digest(first); + } + } + + public static byte[] halfSha512(byte[] bytes) { + return new Sha512(bytes).finish256(); + } + + public static byte[] quarterSha512(byte[] bytes) { + return new Sha512(bytes).finish128(); + } + + public static byte[] sha512(byte[] bytes) { + return new Sha512(bytes).finish(); + } + + public static byte[] SHA256_RIPEMD160(byte[] input) { + try { + byte[] sha256 = MessageDigest.getInstance("SHA-256").digest(input); + RIPEMD160Digest digest = new RIPEMD160Digest(); + digest.update(sha256, 0, sha256.length); + byte[] out = new byte[20]; + digest.doFinal(out, 0); + return out; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); // Cannot happen. + } + } +} diff --git a/ripple-core/src/main/java/com/ripple/utils/Sha512.java b/ripple-core/src/main/java/com/ripple/utils/Sha512.java new file mode 100644 index 0000000000..bafd20b134 --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/utils/Sha512.java @@ -0,0 +1,53 @@ +package com.ripple.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +public class Sha512 { + private MessageDigest messageDigest; + + public Sha512() { + try { + messageDigest = MessageDigest.getInstance("SHA-512"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public Sha512(byte[] start) { + this(); + add(start); + } + + public Sha512 add(byte[] bytes) { + messageDigest.update(bytes); + return this; + } + + public Sha512 addU32(int i) { + messageDigest.update((byte) ((i >>> 24) & 0xFF)); + messageDigest.update((byte) ((i >>> 16) & 0xFF)); + messageDigest.update((byte) ((i >>> 8) & 0xFF)); + messageDigest.update((byte) ((i) & 0xFF)); + return this; + } + + private byte[] finishTaking(int size) { + byte[] hash = new byte[size]; + System.arraycopy(messageDigest.digest(), 0, hash, 0, size); + return hash; + } + + public byte[] finish128() { + return finishTaking(16); + } + + public byte[] finish256() { + return finishTaking(32); + } + + public byte[] finish() { + return messageDigest.digest(); + } +} diff --git a/ripple-core/src/main/java/com/ripple/utils/Utils.java b/ripple-core/src/main/java/com/ripple/utils/Utils.java new file mode 100644 index 0000000000..8376f1637f --- /dev/null +++ b/ripple-core/src/main/java/com/ripple/utils/Utils.java @@ -0,0 +1,58 @@ +package com.ripple.utils; + +import com.ripple.encodings.common.B16; + +import java.math.BigInteger; +import java.util.Arrays; + +public class Utils { + public static String bigHex(BigInteger bn) { + return B16.toStringTrimmed(bn.toByteArray()); + } + + public static BigInteger uBigInt(byte[] bytes) { + return new BigInteger(1, bytes); + } + + public static byte[] leadingZeroesTrimmedOrPaddedTo(int size, byte[] bytes) { + if (bytes.length == size) { + return bytes; + } + if (bytes.length > size) { + int length = bytes.length; + int offset = 0; + while (length > size && bytes[offset++] == 0) { + length--; + } + if (length > size) { + throw new IllegalArgumentException( + "bytes.length: " + bytes.length + " > " + + size); + } + return copyFrom(bytes, offset, size); + } + + return padTo(bytes, size); + } + + public static byte[] padTo256(byte[] bytes) { + return leadingZeroesTrimmedOrPaddedTo(32, bytes); + } + + public static byte[] padTo160(byte[] bytes) { + return leadingZeroesTrimmedOrPaddedTo(20, bytes); + } + + private static byte[] copyFrom(byte[] bytes, int offset, int size) { + byte[] result = new byte[size]; + System.arraycopy(bytes, offset, result, 0, size); + return result; + } + + private static byte[] padTo(byte[] bytes, int size) { + byte[] result = new byte[size]; + int offset = result.length - bytes.length; + System.arraycopy(bytes, 0, result, offset, bytes.length); + return result; + } +} diff --git a/settings.gradle b/settings.gradle index ac821b1c6c..7c7add5bef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':card-android', ':server-android', ':card-common' +include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core' From c77a38ace4072ad97064c80966e65caa948ea4a7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Mar 2019 18:16:18 +0300 Subject: [PATCH 03/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/cardano/CardanoEngine.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java index 089f8e9624..1a0e52dbf4 100644 --- a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java @@ -509,7 +509,7 @@ public class CardanoEngine extends CoinEngine { } @Override - public byte[][] getHashesToSign() throws Exception { + public byte[][] getHashesToSign() { byte[][] dataForSign = new byte[1][]; dataForSign[0] = dataToSign; return dataForSign; @@ -517,17 +517,17 @@ public class CardanoEngine extends CoinEngine { @Override public byte[] getRawDataToSign() throws Exception { - throw new Exception("Signing Raw Data is not supported for Cardano"); + throw new Exception("Signing of raw transaction not supported for " + this.getClass().getSimpleName()); } @Override - public String getHashAlgToSign() { - return "sha-256x2"; + public String getHashAlgToSign() throws Exception { + throw new Exception("Signing of raw transaction not supported for " + this.getClass().getSimpleName()); } @Override public byte[] getIssuerTransactionSignature(byte[] dataToSignByIssuer) throws Exception { - throw new Exception("Issuer validation not supported!"); + throw new Exception("Transaction validation by issuer not supported in this version"); } @Override @@ -625,7 +625,6 @@ public class CardanoEngine extends CoinEngine { if (App.pendingTransactionsStorage.hasTransactions(ctx.getCard())) { for (PendingTransactionsStorage.TransactionInfo pendingTx : App.pendingTransactionsStorage.getTransactions(ctx.getCard()).getTransactions()) { String pendingId = CalculateTxHash(pendingTx.getTx()); - int x = 0; for (TxData walletTx : adaliteResponse.getRight().getCaTxList()) { if (walletTx.getCtbId().equals(pendingId)) { App.pendingTransactionsStorage.removeTransaction(ctx.getCard(), pendingTx.getTx()); From 2adf3e50a6dcfff696e7e3e70af35e22e4f0b2ad Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 22 Mar 2019 12:19:48 +0300 Subject: [PATCH 04/28] Updated on 2026-08-14 --- .../com/tangem/data/network/RippleApi.java | 2 +- .../tangem/data/network/ServerApiRipple.java | 6 +- .../data/network/model/RippleResponse.kt | 17 +- .../tangem/domain/wallet/CoinEngineFactory.kt | 7 +- .../com/tangem/domain/wallet/xrp/XrpData.java | 4 + .../tangem/domain/wallet/xrp/XrpEngine.java | 231 ++++++++++++++---- .../com/tangem/ui/fragment/LoadedWallet.kt | 3 +- 7 files changed, 218 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/com/tangem/data/network/RippleApi.java b/app/src/main/java/com/tangem/data/network/RippleApi.java index 1d457ad859..2b6ad9fe29 100644 --- a/app/src/main/java/com/tangem/data/network/RippleApi.java +++ b/app/src/main/java/com/tangem/data/network/RippleApi.java @@ -10,6 +10,6 @@ import retrofit2.http.POST; public interface RippleApi { @Headers("Content-Type: application/json") - @POST + @POST("./") Call ripple(@Body RippleBody body); } diff --git a/app/src/main/java/com/tangem/data/network/ServerApiRipple.java b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java index ba5c356b47..aee522313f 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiRipple.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java @@ -36,7 +36,7 @@ public class ServerApiRipple { private ResponseListener responseListener; public interface ResponseListener { - void onSuccess(String method, RippleResponse infuraResponse); + void onSuccess(String method, RippleResponse rippleResponse); void onFail(String method, String message); } @@ -45,9 +45,9 @@ public class ServerApiRipple { responseListener = listener; } - public void requestData(String method, int id, String wallet, String tx) { + public void requestData(String method, String wallet, String tx) { requestsCount++; - String rippleURL = "http://s1.ripple.com:51234/"; //TODO: make random selection + String rippleURL = "https://s1.ripple.com:51234"; //TODO: make random selection lastNode = rippleURL; //TODO: show node instead of URL Retrofit retrofitRipple = new Retrofit.Builder() diff --git a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt index 6c61b6abb0..c185403d24 100644 --- a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt +++ b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt @@ -19,12 +19,21 @@ data class RippleResult( var drops: FeeDrops? = null, //for RIPPLE_SUBMIT - @SerializedName("engine_result") - var engine_result: String? = null, + @SerializedName("engine_result_code") + var engine_result_code: Int? = null, //for RIPPLE_SUBMIT @SerializedName ("engine_result_message") - var engine_result_message: String? = null + var engine_result_message: String? = null, + + //for RIPPLE_SUBMIT + @SerializedName("error") + var error: String? = null, + + //for RIPPLE_SUBMIT + @SerializedName("error_exception") + var error_exception: String? = null + ) data class RippleAccountData( @@ -35,7 +44,7 @@ data class RippleAccountData( var balance: String? = null, @SerializedName("Sequence") - var sequence: Int? = null + var sequence: Long? = null ) data class FeeDrops( diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.kt b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.kt index 00e26bc4cb..15c56cef45 100644 --- a/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.kt +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.kt @@ -12,11 +12,13 @@ import com.tangem.domain.wallet.ltc.LtcEngine import com.tangem.domain.wallet.nftToken.NftTokenEngine import com.tangem.domain.wallet.rsk.RskEngine import com.tangem.domain.wallet.rsk.RskTokenEngine +import com.tangem.domain.wallet.xrp.XrpEngine /** * Factory for create specific engine * - * @param Blockchain + * @param + * Blockchain * @param TangemContext * */ @@ -35,6 +37,7 @@ object CoinEngineFactory { Blockchain.Rootstock -> RskEngine() Blockchain.RootstockToken -> RskTokenEngine() Blockchain.Cardano -> CardanoEngine() + Blockchain.Ripple -> XrpEngine() else -> null } } @@ -61,6 +64,8 @@ object CoinEngineFactory { RskTokenEngine(context) else if (Blockchain.Cardano == context.blockchain) CardanoEngine(context) + else if (Blockchain.Ripple == context.blockchain) + XrpEngine(context) else return null } catch (e: Exception) { diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java index 64613e1605..e6f3be777f 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -67,6 +67,10 @@ public class XrpData extends CoinData { this.sequence = sequence; } + public Long getSequence() { + return sequence; + } + public boolean hasBalanceInfo() { return balanceConfirmed != null || balanceUnconfirmed != null; } diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 53ef3e3162..870d6f4eee 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -2,15 +2,19 @@ package com.tangem.domain.wallet.xrp; import android.net.Uri; import android.text.InputFilter; +import android.util.Log; import com.ripple.core.coretypes.AccountID; import com.ripple.core.coretypes.uint.UInt32; import com.ripple.core.types.known.tx.signed.SignedTransaction; import com.ripple.core.types.known.tx.txns.Payment; +import com.ripple.encodings.addresses.Addresses; import com.tangem.card_common.data.TangemCard; import com.tangem.card_common.reader.CardProtocol; import com.tangem.card_common.tasks.SignTask; import com.tangem.card_common.util.Util; +import com.tangem.data.network.ServerApiRipple; +import com.tangem.data.network.model.RippleResponse; import com.tangem.domain.wallet.BTCUtils; import com.tangem.domain.wallet.BalanceValidator; import com.tangem.domain.wallet.CoinData; @@ -23,6 +27,7 @@ import com.tangem.wallet.R; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigDecimal; +import java.math.RoundingMode; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.Arrays; @@ -133,23 +138,9 @@ public class XrpEngine extends CoinEngine { if (!address.startsWith("r")) { return false; } - - byte[] decAddress = XrpBase58.decodeBase58(address); - - if (decAddress == null || decAddress.length == 0) { - return false; - } - - byte[] payload = new byte[21]; - System.arraycopy(decAddress, 0, payload, 0, 21); - - byte[] checksum = new byte[4]; - System.arraycopy(decAddress, 21, checksum, 0, 4); - - byte[] calcChecksum = new byte[4]; - System.arraycopy(CryptoUtil.doubleSha256(payload),0,calcChecksum,0,4); - - if (!Arrays.equals(checksum, calcChecksum)) { + try { + Addresses.decodeAccountID(address); + } catch (Exception e) { return false; } @@ -166,6 +157,10 @@ public class XrpEngine extends CoinEngine { return Uri.parse("https://xrpscan.com/account/" + ctx.getCoinData().getWallet()); } + public Uri getShareWalletUri() { + return Uri.parse(ctx.getCoinData().getWallet()); + } + @Override public InputFilter[] getAmountInputFilters() { return new InputFilter[]{new DecimalDigitsInputFilter(getDecimals())}; @@ -274,18 +269,14 @@ public class XrpEngine extends CoinEngine { return balance.toEquivalentString(coinData.getRate()); } - public String calculateAddress(byte[] pkCompressed) throws NoSuchAlgorithmException, NoSuchProviderException, IOException { - byte[] pkForHash = canonicalPubBytes(pkCompressed); + public String calculateAddress(byte[] pkCompressed) { + byte[] canonisedPubKey = canonisePubKey(pkCompressed); + byte[] accountId = CryptoUtil.sha256ripemd160(canonisedPubKey); + String address = Addresses.encodeAccountID(accountId); - ByteArrayOutputStream address = new ByteArrayOutputStream(); - address.write((byte) 0x00); - byte[] accountId = CryptoUtil.sha256ripemd160(pkForHash); - address.write(accountId); + boolean valid = validateAddress(address); - byte [] doubleSha256 = CryptoUtil.doubleSha256(address.toByteArray()); - address.write(Arrays.copyOfRange(doubleSha256,0,4)); - - return BTCUtils.toHex(address.toByteArray()); + return address; } @Override @@ -337,25 +328,23 @@ public class XrpEngine extends CoinEngine { try { String wallet = calculateAddress(ctx.getCard().getWalletPublicKeyRar()); ctx.getCoinData().setWallet(wallet); - } - catch (Exception e) - { + } catch (Exception e) { ctx.getCoinData().setWallet("ERROR"); throw new CardProtocol.TangemException("Can't define wallet address"); } } - public byte[] canonicalPubBytes(byte[] pkCompressed) { - byte[] pkForHash = new byte[33]; + public byte[] canonisePubKey(byte[] pkCompressed) { + byte[] canonicalPubKey = new byte[33]; if (pkCompressed.length == 32) { - pkForHash[0] = (byte) 0xED; - System.arraycopy(pkCompressed, 0, pkForHash, 1,32); + canonicalPubKey[0] = (byte) 0xED; + System.arraycopy(pkCompressed, 0, canonicalPubKey, 1, 32); } else { - pkForHash = pkCompressed; + canonicalPubKey = pkCompressed; } + return canonicalPubKey; } -} @Override public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception { @@ -364,13 +353,13 @@ public class XrpEngine extends CoinEngine { Payment payment = new Payment(); // Put `as` AccountID field Account, `Object` o - payment.as(AccountID.Account, "rGZG674DSZJfoY8abMPSgChxZTJZEhyMRm"); - payment.as(AccountID.Destination, "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK"); - payment.as(com.ripple.core.coretypes.Amount.Amount, "1000000000"); - payment.as(UInt32.Sequence, 10); - payment.as(com.ripple.core.coretypes.Amount.Fee, "10000"); + payment.as(AccountID.Account, coinData.getWallet()); + payment.as(AccountID.Destination, targetAddress); + payment.as(com.ripple.core.coretypes.Amount.Amount, amountValue); + payment.as(UInt32.Sequence, coinData.getSequence()); + payment.as(com.ripple.core.coretypes.Amount.Fee, feeValue); - SignedTransaction signedTx = payment.prepare(canonicalPubBytes(ctx.getCard().getWalletPublicKeyRar())); + SignedTransaction signedTx = payment.prepare(canonisePubKey(ctx.getCard().getWalletPublicKeyRar())); return new SignTask.TransactionToSign() { @@ -408,4 +397,162 @@ public class XrpEngine extends CoinEngine { } }; } + + public void requestBalanceAndUnspentTransactions(BlockchainRequestsCallbacks blockchainRequestsCallbacks) { + final ServerApiRipple serverApiRipple = new ServerApiRipple(); + + ServerApiRipple.ResponseListener rippleListener = new ServerApiRipple.ResponseListener() { + @Override + public void onSuccess(String method, RippleResponse rippleResponse) { + Log.i(TAG, "onSuccess: " + method); + switch (method) { + case ServerApiRipple.RIPPLE_ACCOUNT_INFO: { + try { + String walletAddress = rippleResponse.getResult().getAccount_data().getAccount(); + if (!walletAddress.equals(coinData.getWallet())) { + throw new Exception("Invalid wallet address in answer!"); + } + + coinData.setBalanceConfirmed(Long.parseLong(rippleResponse.getResult().getAccount_data().getBalance())); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "FAIL RIPPLE_ACCOUNT_INFO Exception"); + } + } + break; + + case ServerApiRipple.RIPPLE_ACCOUNT_UNCONFIRMED: { + try { + String walletAddress = rippleResponse.getResult().getAccount_data().getAccount(); + if (!walletAddress.equals(coinData.getWallet())) { + throw new Exception("Invalid wallet address in answer!"); + } + + coinData.setBalanceReceived(true); + coinData.setBalanceUnconfirmed(Long.parseLong(rippleResponse.getResult().getAccount_data().getBalance())); + coinData.setSequence(rippleResponse.getResult().getAccount_data().getSequence()); + coinData.setValidationNodeDescription(ServerApiRipple.lastNode); + +// //check pending +// if (App.pendingTransactionsStorage.hasTransactions(ctx.getCard())) { +// for (PendingTransactionsStorage.TransactionInfo pendingTx : App.pendingTransactionsStorage.getTransactions(ctx.getCard()).getTransactions()) { +// String pendingId = CalculateTxHash(pendingTx.getTx()); +// int x = 0; +// for (TxData walletTx : adaliteResponse.getRight().getCaTxList()) { +// if (walletTx.getCtbId().equals(pendingId)) { +// App.pendingTransactionsStorage.removeTransaction(ctx.getCard(), pendingTx.getTx()); +// } +// } +// } +// } + + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "FAIL RIPPLE_ACCOUNT_INFO Exception"); + } + } + break; + } + + if (serverApiRipple.isRequestsSequenceCompleted()) { + blockchainRequestsCallbacks.onComplete(!ctx.hasError()); + } else { + blockchainRequestsCallbacks.onProgress(); + } + } + + @Override + public void onFail(String method, String message) { + Log.i(TAG, "onFail: " + method + " " + message); + ctx.setError(message); + if (serverApiRipple.isRequestsSequenceCompleted()) { + blockchainRequestsCallbacks.onComplete(false); + } else { + blockchainRequestsCallbacks.onProgress(); + } + } + }; + + serverApiRipple.setResponseListener(rippleListener); + + serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, coinData.getWallet(), ""); + serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_UNCONFIRMED, coinData.getWallet(), ""); + } + + @Override + public void requestFee(BlockchainRequestsCallbacks blockchainRequestsCallbacks, String targetAddress, Amount amount) { + final ServerApiRipple serverApiRipple = new ServerApiRipple(); + + ServerApiRipple.ResponseListener rippleListener = new ServerApiRipple.ResponseListener() { + @Override + public void onSuccess(String method, RippleResponse rippleResponse) { + BigDecimal minFee = new BigDecimal(rippleResponse.getResult().getDrops().getMinimum_fee()).divide(new BigDecimal(getDecimals())); + BigDecimal normalFee = new BigDecimal(rippleResponse.getResult().getDrops().getOpen_ledger_fee()).divide(new BigDecimal(getDecimals())); + BigDecimal maxFee = new BigDecimal(rippleResponse.getResult().getDrops().getMedian_fee()).divide(new BigDecimal(getDecimals())); + + coinData.minFee = new Amount(minFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); + coinData.normalFee = new Amount(normalFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); + coinData.maxFee = new Amount(maxFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); + + blockchainRequestsCallbacks.onComplete(true); + } + + @Override + public void onFail(String method, String message) { + Log.i(TAG, "onFail: " + method + " " + message); + ctx.setError(message); + blockchainRequestsCallbacks.onComplete(false); + } + }; + + serverApiRipple.setResponseListener(rippleListener); + + serverApiRipple.requestData(ServerApiRipple.RIPPLE_FEE, "", ""); + } + + @Override + public void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) { + final String txStr = BTCUtils.toHex(txForSend); + + final ServerApiRipple serverApiRipple = new ServerApiRipple(); + + final ServerApiRipple.ResponseListener responseListener = new ServerApiRipple.ResponseListener() { + @Override + public void onSuccess(String method, RippleResponse rippleResponse) { + try { + if (rippleResponse.getResult().getEngine_result_code() != null) { + if (rippleResponse.getResult().getEngine_result_code() == 0) { + ctx.setError(null); + blockchainRequestsCallbacks.onComplete(true); + } else { + ctx.setError(rippleResponse.getResult().getEngine_result_message()); + blockchainRequestsCallbacks.onComplete(false); + } + } else { + ctx.setError(rippleResponse.getResult().getError() + " - " + rippleResponse.getResult().getError_exception()); + blockchainRequestsCallbacks.onComplete(false); + } + } catch (Exception e) { + if (e.getMessage() != null) { + ctx.setError(e.getMessage()); + blockchainRequestsCallbacks.onComplete(false); + } else { + ctx.setError(e.getClass().getName()); + blockchainRequestsCallbacks.onComplete(false); + Log.e(TAG, rippleResponse.toString()); + } + } + } + + @Override + public void onFail(String method, String message) { + ctx.setError(message); + blockchainRequestsCallbacks.onComplete(false); + } + }; + serverApiRipple.setResponseListener(responseListener); + + serverApiRipple.requestData(ServerApiRipple.RIPPLE_SUBMIT, "", txStr); + } + } diff --git a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt index 1e27ef605a..346f7900be 100644 --- a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt @@ -143,7 +143,7 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback tvWallet.setOnClickListener { doShareWallet(false) } - btnExplore.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, engine?.walletExplorerUri)) } + btnExplore.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, engine.walletExplorerUri)) } btnCopy.setOnClickListener { doShareWallet(false) } @@ -730,6 +730,7 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback Blockchain.Rootstock -> "bitcoin" Blockchain.RootstockToken -> "bitcoin" Blockchain.Cardano -> "cardano" + Blockchain.Ripple -> "ripple" else -> { throw Exception("Can''t get rate for blockchain " + ctx.blockchainName) } From 131ccfe7dfce42a14cea8260b40f5252d03b6b85 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Mar 2019 14:49:50 +0300 Subject: [PATCH 05/28] Updated on 2026-08-14 --- .../main/java/com/tangem/domain/wallet/rsk/RskEngine.java | 5 +++++ .../java/com/tangem/domain/wallet/rsk/RskTokenEngine.java | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java index fd67467442..a82a04e799 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskEngine.java @@ -56,6 +56,11 @@ public class RskEngine extends EthEngine { return Uri.parse("https://explorer.rsk.co/address/" + ctx.getCoinData().getWallet()); } + @Override + public String evaluateFeeEquivalent(String fee) { + return ""; + } + @Override public void requestBalanceAndUnspentTransactions(BlockchainRequestsCallbacks blockchainRequestsCallbacks) { final ServerApiRootstock serverApiRootstock = new ServerApiRootstock(); diff --git a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java index e23a529db2..c71992239d 100644 --- a/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/rsk/RskTokenEngine.java @@ -40,7 +40,7 @@ public class RskTokenEngine extends TokenEngine { @Override public Uri getWalletExplorerUri() { return Uri.parse("https://explorer.rsk.co/address/" + ctx.getCoinData().getWallet() + "?__tab=tokens"); - } // Only RSK explorer for now + } @Override public Uri getShareWalletUri() { @@ -63,6 +63,11 @@ public class RskTokenEngine extends TokenEngine { return false; } + @Override + public String evaluateFeeEquivalent(String fee) { + return ""; + } + @Override public void requestBalanceAndUnspentTransactions(BlockchainRequestsCallbacks blockchainRequestsCallbacks) { final ServerApiRootstock serverApiRootstock = new ServerApiRootstock(); From d3f93a7dc8e05d1c2f3ea79fb888a2ccb88e2981 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Mar 2019 18:28:59 +0300 Subject: [PATCH 06/28] Updated on 2026-08-14 --- .../com/tangem/domain/wallet/xrp/XrpData.java | 8 ++++++-- .../tangem/domain/wallet/xrp/XrpEngine.java | 19 ++++++++++++------- .../tangem/card_common/tasks/SignTask.java | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java index e6f3be777f..3b46f27be9 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -21,7 +21,8 @@ public class XrpData extends CoinData { if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); else balanceConfirmed = null; - if (B.containsKey("BalanceUnconfirmed")) balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); + if (B.containsKey("BalanceUnconfirmed")) + balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); else balanceUnconfirmed = null; if (B.containsKey("Sequence")) sequence = B.getLong("Sequence"); } @@ -48,7 +49,10 @@ public class XrpData extends CoinData { // balanceUnconfirmed is just the latest balance, it equals balanceConfirmed if no unconfirmed transaction present public CoinEngine.InternalAmount getBalanceInInternalUnits() { - return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed), "Drops"); + if (balanceUnconfirmed != null) + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed), "Drops"); + else + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceConfirmed), "Drops"); } // public Long getBalanceUnconfirmed() { diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 870d6f4eee..3ff88f45dc 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -350,14 +350,17 @@ public class XrpEngine extends CoinEngine { public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception { checkBlockchainDataExists(); + String amount = Long.toString(convertToInternalAmount(amountValue).longValueExact()); + String fee = Long.toString(convertToInternalAmount(feeValue).longValueExact()); + Payment payment = new Payment(); // Put `as` AccountID field Account, `Object` o payment.as(AccountID.Account, coinData.getWallet()); payment.as(AccountID.Destination, targetAddress); - payment.as(com.ripple.core.coretypes.Amount.Amount, amountValue); + payment.as(com.ripple.core.coretypes.Amount.Amount, amount); payment.as(UInt32.Sequence, coinData.getSequence()); - payment.as(com.ripple.core.coretypes.Amount.Fee, feeValue); + payment.as(com.ripple.core.coretypes.Amount.Fee, fee); SignedTransaction signedTx = payment.prepare(canonisePubKey(ctx.getCard().getWalletPublicKeyRar())); @@ -391,9 +394,11 @@ public class XrpEngine extends CoinEngine { } @Override - public byte[] onSignCompleted(byte[] signFromCard) { + public byte[] onSignCompleted(byte[] signFromCard) throws Exception { signedTx.addSign(signFromCard); - return BTCUtils.fromHex(signedTx.tx_blob); + byte[] txForSend = BTCUtils.fromHex(signedTx.tx_blob); + notifyOnNeedSendTransaction(txForSend); + return txForSend; } }; } @@ -486,9 +491,9 @@ public class XrpEngine extends CoinEngine { ServerApiRipple.ResponseListener rippleListener = new ServerApiRipple.ResponseListener() { @Override public void onSuccess(String method, RippleResponse rippleResponse) { - BigDecimal minFee = new BigDecimal(rippleResponse.getResult().getDrops().getMinimum_fee()).divide(new BigDecimal(getDecimals())); - BigDecimal normalFee = new BigDecimal(rippleResponse.getResult().getDrops().getOpen_ledger_fee()).divide(new BigDecimal(getDecimals())); - BigDecimal maxFee = new BigDecimal(rippleResponse.getResult().getDrops().getMedian_fee()).divide(new BigDecimal(getDecimals())); + BigDecimal minFee = new BigDecimal(Long.valueOf(rippleResponse.getResult().getDrops().getMinimum_fee())).divide(new BigDecimal(1000000)); + BigDecimal normalFee = new BigDecimal(Long.valueOf(rippleResponse.getResult().getDrops().getOpen_ledger_fee())).divide(new BigDecimal(1000000)); + BigDecimal maxFee = new BigDecimal(Long.valueOf(rippleResponse.getResult().getDrops().getMedian_fee())).divide(new BigDecimal(1000000)); coinData.minFee = new Amount(minFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); coinData.normalFee = new Amount(normalFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); diff --git a/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java b/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java index 7d4a0d5d8e..d3eebd6bda 100644 --- a/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java +++ b/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java @@ -85,6 +85,7 @@ public class SignTask extends CustomReadCardTask { } transactionToSign.onSignCompleted(signResult.getTLV(TLV.Tag.TAG_Signature).Value); + //TODO: maybe we should move notifyOnNeedSendTransaction(txForSend) here? mNotifications.onReadProgress(protocol, 100); } From 9f3ce2ce3c24dad36b11f06c23539583a1bb0f61 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 25 Mar 2019 18:28:59 +0300 Subject: [PATCH 07/28] Updated on 2026-08-14 --- .../com/tangem/domain/wallet/xrp/XrpData.java | 17 +++++++- .../tangem/domain/wallet/xrp/XrpEngine.java | 43 +++++++++++++------ .../tangem/card_common/tasks/SignTask.java | 1 + 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java index e6f3be777f..76f3c70eb7 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -14,6 +14,7 @@ public class XrpData extends CoinData { } private Long balanceConfirmed, balanceUnconfirmed, sequence; + private Long reserve = 20000000L; @Override public void loadFromBundle(Bundle B) { @@ -21,7 +22,8 @@ public class XrpData extends CoinData { if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); else balanceConfirmed = null; - if (B.containsKey("BalanceUnconfirmed")) balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); + if (B.containsKey("BalanceUnconfirmed")) + balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); else balanceUnconfirmed = null; if (B.containsKey("Sequence")) sequence = B.getLong("Sequence"); } @@ -48,7 +50,10 @@ public class XrpData extends CoinData { // balanceUnconfirmed is just the latest balance, it equals balanceConfirmed if no unconfirmed transaction present public CoinEngine.InternalAmount getBalanceInInternalUnits() { - return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed), "Drops"); + if (balanceUnconfirmed != null) + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceUnconfirmed).subtract(BigDecimal.valueOf(reserve)), "Drops"); + else + return new CoinEngine.InternalAmount(BigDecimal.valueOf(balanceConfirmed).subtract(BigDecimal.valueOf(reserve)), "Drops"); } // public Long getBalanceUnconfirmed() { @@ -71,6 +76,14 @@ public class XrpData extends CoinData { return sequence; } + public void setReserve(Long reserve) { + this.reserve = reserve; + } + + public CoinEngine.InternalAmount getReserveInInternalUnits() { + return new CoinEngine.InternalAmount(BigDecimal.valueOf(reserve), "Drops"); + } + public boolean hasBalanceInfo() { return balanceConfirmed != null || balanceUnconfirmed != null; } diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 870d6f4eee..7ed6e32161 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -72,7 +72,7 @@ public class XrpEngine extends CoinEngine { public String getBalanceHTML() { Amount balance = getBalance(); if (balance != null) { - return balance.toDescriptionString(getDecimals()); + return " " + balance.toDescriptionString(getDecimals()) + "
+ " + convertToAmount(coinData.getReserveInInternalUnits()).toDescriptionString(getDecimals()) + " reserve"; } else { return ""; } @@ -158,7 +158,7 @@ public class XrpEngine extends CoinEngine { } public Uri getShareWalletUri() { - return Uri.parse(ctx.getCoinData().getWallet()); + return Uri.parse("ripple:" + ctx.getCoinData().getWallet()); } @Override @@ -350,14 +350,24 @@ public class XrpEngine extends CoinEngine { public SignTask.TransactionToSign constructTransaction(Amount amountValue, Amount feeValue, boolean IncFee, String targetAddress) throws Exception { checkBlockchainDataExists(); + String amount, fee; + + if (IncFee) { + amount = convertToInternalAmount(amountValue).subtract(convertToInternalAmount(feeValue)).setScale(0).toPlainString(); + } else { + amount = Long.toString(convertToInternalAmount(amountValue).longValueExact()); + } + + fee = Long.toString(convertToInternalAmount(feeValue).longValueExact()); + Payment payment = new Payment(); // Put `as` AccountID field Account, `Object` o payment.as(AccountID.Account, coinData.getWallet()); payment.as(AccountID.Destination, targetAddress); - payment.as(com.ripple.core.coretypes.Amount.Amount, amountValue); + payment.as(com.ripple.core.coretypes.Amount.Amount, amount); payment.as(UInt32.Sequence, coinData.getSequence()); - payment.as(com.ripple.core.coretypes.Amount.Fee, feeValue); + payment.as(com.ripple.core.coretypes.Amount.Fee, fee); SignedTransaction signedTx = payment.prepare(canonisePubKey(ctx.getCard().getWalletPublicKeyRar())); @@ -391,9 +401,11 @@ public class XrpEngine extends CoinEngine { } @Override - public byte[] onSignCompleted(byte[] signFromCard) { + public byte[] onSignCompleted(byte[] signFromCard) throws Exception { signedTx.addSign(signFromCard); - return BTCUtils.fromHex(signedTx.tx_blob); + byte[] txForSend = BTCUtils.fromHex(signedTx.tx_blob); + notifyOnNeedSendTransaction(txForSend); + return txForSend; } }; } @@ -486,13 +498,13 @@ public class XrpEngine extends CoinEngine { ServerApiRipple.ResponseListener rippleListener = new ServerApiRipple.ResponseListener() { @Override public void onSuccess(String method, RippleResponse rippleResponse) { - BigDecimal minFee = new BigDecimal(rippleResponse.getResult().getDrops().getMinimum_fee()).divide(new BigDecimal(getDecimals())); - BigDecimal normalFee = new BigDecimal(rippleResponse.getResult().getDrops().getOpen_ledger_fee()).divide(new BigDecimal(getDecimals())); - BigDecimal maxFee = new BigDecimal(rippleResponse.getResult().getDrops().getMedian_fee()).divide(new BigDecimal(getDecimals())); + InternalAmount minFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMinimum_fee()), "Drops"); + InternalAmount normalFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getOpen_ledger_fee()), "Drops"); + InternalAmount maxFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMedian_fee()), "Drops"); - coinData.minFee = new Amount(minFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); - coinData.normalFee = new Amount(normalFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); - coinData.maxFee = new Amount(maxFee.setScale(getDecimals(), RoundingMode.UP), getFeeCurrency()); + coinData.minFee = convertToAmount(minFee); + coinData.normalFee = convertToAmount(normalFee); + coinData.maxFee = convertToAmount(maxFee); blockchainRequestsCallbacks.onComplete(true); } @@ -555,4 +567,11 @@ public class XrpEngine extends CoinEngine { serverApiRipple.requestData(ServerApiRipple.RIPPLE_SUBMIT, "", txStr); } + @Override + public int pendingTransactionTimeoutInSeconds() { return 10; } + + public boolean needMultipleLinesForBalance() { + return true; + } + } diff --git a/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java b/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java index 7d4a0d5d8e..d3eebd6bda 100644 --- a/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java +++ b/card-common/src/main/java/com/tangem/card_common/tasks/SignTask.java @@ -85,6 +85,7 @@ public class SignTask extends CustomReadCardTask { } transactionToSign.onSignCompleted(signResult.getTLV(TLV.Tag.TAG_Signature).Value); + //TODO: maybe we should move notifyOnNeedSendTransaction(txForSend) here? mNotifications.onReadProgress(protocol, 100); } From aed5a8558f119480552e9803da18246b6948229b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Mar 2019 18:57:13 +0300 Subject: [PATCH 08/28] Updated on 2026-08-14 --- .../com/tangem/data/network/model/AdaliteResponse.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/data/network/model/AdaliteResponse.kt b/app/src/main/java/com/tangem/data/network/model/AdaliteResponse.kt index 2c1602b513..d560d5fefc 100644 --- a/app/src/main/java/com/tangem/data/network/model/AdaliteResponse.kt +++ b/app/src/main/java/com/tangem/data/network/model/AdaliteResponse.kt @@ -4,15 +4,15 @@ import com.google.gson.annotations.SerializedName data class AdaliteResponse( @SerializedName("Right") - var right: AddressData? = null + var right: AdaliteAddressData? = null ) data class AdaliteResponseUtxo( @SerializedName("Right") - var right: List + var right: List ) -data class AddressData( +data class AdaliteAddressData( @SerializedName("caAddress") var caAddress: String? = null, @@ -20,7 +20,7 @@ data class AddressData( var caBalance: AdaliteCoins? = null, @SerializedName("caTxList") - var caTxList: List + var caTxList: List ) data class AdaliteCoins( @@ -28,7 +28,7 @@ data class AdaliteCoins( var getCoin: Long? = null ) -data class UtxoData( +data class AdaliteUtxoData( @SerializedName("cuId") var cuId: String? = null, @@ -39,7 +39,7 @@ data class UtxoData( var cuCoins: AdaliteCoins? = null ) -data class TxData( +data class AdaliteTxData( @SerializedName("ctbId") var ctbId: String? = null ) \ No newline at end of file From bacb21c115e5118032c4e3449010a3fc1429d70b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Mar 2019 13:31:05 +0300 Subject: [PATCH 09/28] Updated on 2026-08-14 --- .../tangem/data/network/ServerApiRipple.java | 9 ++-- .../data/network/model/RippleResponse.kt | 19 ++++++-- .../domain/wallet/cardano/CardanoEngine.java | 8 ++-- .../com/tangem/domain/wallet/xrp/XrpData.java | 9 +++- .../tangem/domain/wallet/xrp/XrpEngine.java | 44 ++++++++++++------- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/tangem/data/network/ServerApiRipple.java b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java index aee522313f..ddbe82e090 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiRipple.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiRipple.java @@ -2,12 +2,10 @@ package com.tangem.data.network; import android.util.Log; -import com.tangem.App; import com.tangem.data.network.model.RippleBody; import com.tangem.data.network.model.RippleResponse; import java.util.HashMap; -import java.util.Map; import androidx.annotation.NonNull; import retrofit2.Call; @@ -23,8 +21,9 @@ public class ServerApiRipple { public static final String RIPPLE_ACCOUNT_UNCONFIRMED = "account_unconfirmed"; public static final String RIPPLE_SUBMIT = "submit"; public static final String RIPPLE_FEE = "fee"; + public static final String RIPPLE_SERVER_STATE = "server_state"; - private int requestsCount=0; + private int requestsCount = 0; public static String lastNode; @@ -76,6 +75,10 @@ public class ServerApiRipple { rippleBody = new RippleBody(RIPPLE_ACCOUNT_INFO, paramsMap); break; + case RIPPLE_SERVER_STATE: + rippleBody = new RippleBody(method, new HashMap<>()); + break; + case RIPPLE_FEE: rippleBody = new RippleBody(method, new HashMap<>()); break; diff --git a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt index c185403d24..d8d54ba683 100644 --- a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt +++ b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt @@ -16,7 +16,7 @@ data class RippleResult( //for RIPPLE_FEE @SerializedName("drops") - var drops: FeeDrops? = null, + var drops: RippleFeeDrops? = null, //for RIPPLE_SUBMIT @SerializedName("engine_result_code") @@ -32,8 +32,11 @@ data class RippleResult( //for RIPPLE_SUBMIT @SerializedName("error_exception") - var error_exception: String? = null + var error_exception: String? = null, + //for RIPPLE_SERVER_STATE + @SerializedName("state") + var state: RippleState? = null ) data class RippleAccountData( @@ -47,7 +50,7 @@ data class RippleAccountData( var sequence: Long? = null ) -data class FeeDrops( +data class RippleFeeDrops( //enough to put tx to queue @SerializedName("minimum_fee") var minimum_fee: String? = null, @@ -58,4 +61,14 @@ data class FeeDrops( @SerializedName("median_fee") var median_fee: String? = null +) + +data class RippleState( + @SerializedName("validated_ledger") + var validated_ledger: RippleLedger? = null +) + +data class RippleLedger( + @SerializedName("reserve_base") + var reserve_base: Long? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java index 1a0e52dbf4..901d4bcfef 100644 --- a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java @@ -10,8 +10,8 @@ import com.tangem.data.local.PendingTransactionsStorage; import com.tangem.data.network.ServerApiAdalite; import com.tangem.data.network.model.AdaliteResponse; import com.tangem.data.network.model.AdaliteResponseUtxo; -import com.tangem.data.network.model.TxData; -import com.tangem.data.network.model.UtxoData; +import com.tangem.data.network.model.AdaliteTxData; +import com.tangem.data.network.model.AdaliteUtxoData; import com.tangem.domain.wallet.BTCUtils; import com.tangem.domain.wallet.BalanceValidator; import com.tangem.domain.wallet.Base58; @@ -625,7 +625,7 @@ public class CardanoEngine extends CoinEngine { if (App.pendingTransactionsStorage.hasTransactions(ctx.getCard())) { for (PendingTransactionsStorage.TransactionInfo pendingTx : App.pendingTransactionsStorage.getTransactions(ctx.getCard()).getTransactions()) { String pendingId = CalculateTxHash(pendingTx.getTx()); - for (TxData walletTx : adaliteResponse.getRight().getCaTxList()) { + for (AdaliteTxData walletTx : adaliteResponse.getRight().getCaTxList()) { if (walletTx.getCtbId().equals(pendingId)) { App.pendingTransactionsStorage.removeTransaction(ctx.getCard(), pendingTx.getTx()); } @@ -651,7 +651,7 @@ public class CardanoEngine extends CoinEngine { Log.i(TAG, "onSuccess: " + method); try { coinData.getUnspentOutputs().clear(); - for (UtxoData utxo : adaliteResponseUtxo.getRight()) { + for (AdaliteUtxoData utxo : adaliteResponseUtxo.getRight()) { CardanoData.UnspentOutput unspentOutput = new CardanoData.UnspentOutput(); unspentOutput.txID = utxo.getCuId(); unspentOutput.Amount = utxo.getCuCoins().getGetCoin(); diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java index 76f3c70eb7..180f454a37 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -14,6 +14,7 @@ public class XrpData extends CoinData { } private Long balanceConfirmed, balanceUnconfirmed, sequence; + private Long reserve = 20000000L; @Override @@ -22,10 +23,12 @@ public class XrpData extends CoinData { if (B.containsKey("BalanceConfirmed")) balanceConfirmed = B.getLong("BalanceConfirmed"); else balanceConfirmed = null; - if (B.containsKey("BalanceUnconfirmed")) - balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); + if (B.containsKey("BalanceUnconfirmed")) balanceUnconfirmed = B.getLong("BalanceUnconfirmed"); else balanceUnconfirmed = null; if (B.containsKey("Sequence")) sequence = B.getLong("Sequence"); + else sequence = null; + if (B.containsKey("Reserve")) reserve = B.getLong("Reserve"); + else reserve = 20000000L; } @Override @@ -35,6 +38,7 @@ public class XrpData extends CoinData { if (balanceConfirmed != null) B.putLong("BalanceConfirmed", balanceConfirmed); if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed); if (sequence != null) B.putLong("Sequence", sequence); + if (reserve != null) B.putLong("Reserve", reserve); } catch (Exception e) { Log.e("Can't save to bundle ", e.getMessage()); } @@ -46,6 +50,7 @@ public class XrpData extends CoinData { balanceConfirmed = null; balanceUnconfirmed = null; sequence = null; + reserve = 20000000L; } // balanceUnconfirmed is just the latest balance, it equals balanceConfirmed if no unconfirmed transaction present diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 7ed6e32161..48aa9a47ce 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -24,13 +24,7 @@ import com.tangem.util.CryptoUtil; import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.wallet.R; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.math.BigDecimal; -import java.math.RoundingMode; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.util.Arrays; public class XrpEngine extends CoinEngine { @@ -450,7 +444,7 @@ public class XrpEngine extends CoinEngine { // for (PendingTransactionsStorage.TransactionInfo pendingTx : App.pendingTransactionsStorage.getTransactions(ctx.getCard()).getTransactions()) { // String pendingId = CalculateTxHash(pendingTx.getTx()); // int x = 0; -// for (TxData walletTx : adaliteResponse.getRight().getCaTxList()) { +// for (AdaliteTxData walletTx : adaliteResponse.getRight().getCaTxList()) { // if (walletTx.getCtbId().equals(pendingId)) { // App.pendingTransactionsStorage.removeTransaction(ctx.getCard(), pendingTx.getTx()); // } @@ -464,6 +458,16 @@ public class XrpEngine extends CoinEngine { } } break; + + case ServerApiRipple.RIPPLE_SERVER_STATE: { + try { + coinData.setReserve(rippleResponse.getResult().getState().getValidated_ledger().getReserve_base()); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "FAIL RIPPLE_ACCOUNT_INFO Exception"); + } + } + break; } if (serverApiRipple.isRequestsSequenceCompleted()) { @@ -489,6 +493,7 @@ public class XrpEngine extends CoinEngine { serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_INFO, coinData.getWallet(), ""); serverApiRipple.requestData(ServerApiRipple.RIPPLE_ACCOUNT_UNCONFIRMED, coinData.getWallet(), ""); + serverApiRipple.requestData(ServerApiRipple.RIPPLE_SERVER_STATE, "", ""); } @Override @@ -498,15 +503,20 @@ public class XrpEngine extends CoinEngine { ServerApiRipple.ResponseListener rippleListener = new ServerApiRipple.ResponseListener() { @Override public void onSuccess(String method, RippleResponse rippleResponse) { - InternalAmount minFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMinimum_fee()), "Drops"); - InternalAmount normalFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getOpen_ledger_fee()), "Drops"); - InternalAmount maxFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMedian_fee()), "Drops"); + try { + InternalAmount minFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMinimum_fee()), "Drops"); + InternalAmount normalFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getOpen_ledger_fee()), "Drops"); + InternalAmount maxFee = new InternalAmount(Long.valueOf(rippleResponse.getResult().getDrops().getMedian_fee()), "Drops"); - coinData.minFee = convertToAmount(minFee); - coinData.normalFee = convertToAmount(normalFee); - coinData.maxFee = convertToAmount(maxFee); + coinData.minFee = convertToAmount(minFee); + coinData.normalFee = convertToAmount(normalFee); + coinData.maxFee = convertToAmount(maxFee); - blockchainRequestsCallbacks.onComplete(true); + blockchainRequestsCallbacks.onComplete(true); + } catch (Exception e) { + e.printStackTrace(); + Log.e(TAG, "FAIL RIPPLE_FEE Exception"); + } } @Override @@ -524,7 +534,7 @@ public class XrpEngine extends CoinEngine { @Override public void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) { - final String txStr = BTCUtils.toHex(txForSend); + final String txStr = BTCUtils.toHex(txForSend); final ServerApiRipple serverApiRipple = new ServerApiRipple(); @@ -568,7 +578,9 @@ public class XrpEngine extends CoinEngine { } @Override - public int pendingTransactionTimeoutInSeconds() { return 10; } + public int pendingTransactionTimeoutInSeconds() { + return 10; + } public boolean needMultipleLinesForBalance() { return true; From 639e1fe7939a9cf1dcddcdeeae2f4a9bdd5f9ff0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 29 Mar 2019 15:17:25 +0300 Subject: [PATCH 10/28] Updated on 2026-08-14 --- .../data/network/model/RippleResponse.kt | 6 +- .../com/tangem/domain/wallet/CoinEngine.java | 2 +- .../com/tangem/domain/wallet/xrp/XrpData.java | 14 ++++ .../tangem/domain/wallet/xrp/XrpEngine.java | 67 ++++++++++++++----- .../com/tangem/ui/fragment/LoadedWallet.kt | 2 +- 5 files changed, 72 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt index d8d54ba683..4a865aca67 100644 --- a/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt +++ b/app/src/main/java/com/tangem/data/network/model/RippleResponse.kt @@ -36,7 +36,11 @@ data class RippleResult( //for RIPPLE_SERVER_STATE @SerializedName("state") - var state: RippleState? = null + var state: RippleState? = null, + + //for "Account not found error" + @SerializedName("error_code") + var error_code: Int? = null ) data class RippleAccountData( diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java index f539bb9443..5936584616 100644 --- a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java @@ -216,7 +216,7 @@ public abstract class CoinEngine { public abstract boolean validateAddress(String address); - public abstract String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException, CborException, IOException; + public abstract String calculateAddress(byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException, CborException, IOException, Exception; public abstract Amount convertToAmount(InternalAmount internalAmount) throws Exception; diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java index 180f454a37..a44db475f8 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpData.java @@ -17,6 +17,8 @@ public class XrpData extends CoinData { private Long reserve = 20000000L; + private Boolean accountNotFound = false; + @Override public void loadFromBundle(Bundle B) { super.loadFromBundle(B); @@ -29,6 +31,8 @@ public class XrpData extends CoinData { else sequence = null; if (B.containsKey("Reserve")) reserve = B.getLong("Reserve"); else reserve = 20000000L; + if (B.containsKey("AccoundNotFound")) accountNotFound = B.getBoolean("AccoundNotFound"); + else reserve = 20000000L; } @Override @@ -39,6 +43,7 @@ public class XrpData extends CoinData { if (balanceUnconfirmed != null) B.putLong("BalanceUnconfirmed", balanceUnconfirmed); if (sequence != null) B.putLong("Sequence", sequence); if (reserve != null) B.putLong("Reserve", reserve); + if (accountNotFound != null) B.putBoolean("AccoundNotFound", accountNotFound); } catch (Exception e) { Log.e("Can't save to bundle ", e.getMessage()); } @@ -51,6 +56,7 @@ public class XrpData extends CoinData { balanceUnconfirmed = null; sequence = null; reserve = 20000000L; + accountNotFound = false; } // balanceUnconfirmed is just the latest balance, it equals balanceConfirmed if no unconfirmed transaction present @@ -89,6 +95,14 @@ public class XrpData extends CoinData { return new CoinEngine.InternalAmount(BigDecimal.valueOf(reserve), "Drops"); } + public boolean isAccountNotFound() { + return accountNotFound; + } + + public void setAccountNotFound(boolean accountFound) { + this.accountNotFound = accountFound; + } + public boolean hasBalanceInfo() { return balanceConfirmed != null || balanceUnconfirmed != null; } diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 48aa9a47ce..fda44e7931 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -8,7 +8,9 @@ import com.ripple.core.coretypes.AccountID; import com.ripple.core.coretypes.uint.UInt32; import com.ripple.core.types.known.tx.signed.SignedTransaction; import com.ripple.core.types.known.tx.txns.Payment; +import com.ripple.crypto.ecdsa.ECDSASignature; import com.ripple.encodings.addresses.Addresses; +import com.ripple.utils.HashUtils; import com.tangem.card_common.data.TangemCard; import com.tangem.card_common.reader.CardProtocol; import com.tangem.card_common.tasks.SignTask; @@ -24,7 +26,13 @@ import com.tangem.util.CryptoUtil; import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.wallet.R; +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERSequence; + import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; public class XrpEngine extends CoinEngine { @@ -66,7 +74,7 @@ public class XrpEngine extends CoinEngine { public String getBalanceHTML() { Amount balance = getBalance(); if (balance != null) { - return " " + balance.toDescriptionString(getDecimals()) + "
+ " + convertToAmount(coinData.getReserveInInternalUnits()).toDescriptionString(getDecimals()) + " reserve"; + return " " + balance.toDescriptionString(getDecimals()) + "
+ " + convertToAmount(coinData.getReserveInInternalUnits()).toDescriptionString(getDecimals()) + " reserve"; } else { return ""; } @@ -201,6 +209,13 @@ public class XrpEngine extends CoinEngine { @Override public boolean validateBalance(BalanceValidator balanceValidator) { try { + if (coinData.isAccountNotFound()) { + balanceValidator.setScore(0); + balanceValidator.setFirstLine("Account not found"); + balanceValidator.setSecondLine("Load 20+ XRP to create account"); + return false; + } + if (((ctx.getCard().getOfflineBalance() == null) && !ctx.getCoinData().isBalanceReceived()) || (!ctx.getCoinData().isBalanceReceived() && (ctx.getCard().getRemainingSignatures() != ctx.getCard().getMaxSignatures()))) { balanceValidator.setScore(0); balanceValidator.setFirstLine("Unknown balance"); @@ -263,7 +278,7 @@ public class XrpEngine extends CoinEngine { return balance.toEquivalentString(coinData.getRate()); } - public String calculateAddress(byte[] pkCompressed) { + public String calculateAddress(byte[] pkCompressed) throws Exception { byte[] canonisedPubKey = canonisePubKey(pkCompressed); byte[] accountId = CryptoUtil.sha256ripemd160(canonisedPubKey); String address = Addresses.encodeAccountID(accountId); @@ -301,9 +316,6 @@ public class XrpEngine extends CoinEngine { @Override public byte[] convertToByteArray(InternalAmount internalAmount) { byte[] bytes = Util.longToByteArray(internalAmount.longValueExact()); -// byte[] reversed = new byte[bytes.length]; TODO: check if needed -// for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; -// return reversed; return bytes; } @@ -328,15 +340,16 @@ public class XrpEngine extends CoinEngine { } } - public byte[] canonisePubKey(byte[] pkCompressed) { + public byte[] canonisePubKey(byte[] pkCompressed) throws Exception { byte[] canonicalPubKey = new byte[33]; if (pkCompressed.length == 32) { canonicalPubKey[0] = (byte) 0xED; System.arraycopy(pkCompressed, 0, canonicalPubKey, 1, 32); - } else { + } else if (pkCompressed.length == 33) canonicalPubKey = pkCompressed; - } + else + throw new Exception("Invalid pubkey length"); return canonicalPubKey; } @@ -373,9 +386,14 @@ public class XrpEngine extends CoinEngine { } @Override - public byte[][] getHashesToSign() { + public byte[][] getHashesToSign() throws Exception { byte[][] dataForSign = new byte[1][]; - dataForSign[0] = signedTx.signingData; + if (ctx.getCard().getWalletPublicKeyRar().length == 33) + dataForSign[0] = HashUtils.halfSha512(signedTx.signingData); + else if (ctx.getCard().getWalletPublicKeyRar().length == 32) + dataForSign[0] = signedTx.signingData; + else + throw new Exception("Invalid pubkey length"); return dataForSign; } @@ -396,7 +414,21 @@ public class XrpEngine extends CoinEngine { @Override public byte[] onSignCompleted(byte[] signFromCard) throws Exception { - signedTx.addSign(signFromCard); + if (ctx.getCard().getWalletPublicKeyRar().length == 33) { + int size = signFromCard.length / 2; + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, size)); + BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, size, size * 2)); + s = CryptoUtil.toCanonicalised(s); + ECDSASignature sig = new ECDSASignature(r, s); + byte[] sigDer = sig.encodeToDER(); + if (!ECDSASignature.isStrictlyCanonical(sigDer)) { + throw new IllegalStateException("Signature is not strictly canonical"); + } + signedTx.addSign(sigDer); + } else if (ctx.getCard().getWalletPublicKeyRar().length == 32) + signedTx.addSign(signFromCard); + else + throw new Exception("Invalid pubkey length"); byte[] txForSend = BTCUtils.fromHex(signedTx.tx_blob); notifyOnNeedSendTransaction(txForSend); return txForSend; @@ -414,12 +446,15 @@ public class XrpEngine extends CoinEngine { switch (method) { case ServerApiRipple.RIPPLE_ACCOUNT_INFO: { try { - String walletAddress = rippleResponse.getResult().getAccount_data().getAccount(); - if (!walletAddress.equals(coinData.getWallet())) { - throw new Exception("Invalid wallet address in answer!"); + if (rippleResponse.getResult().getAccount_data() != null) { + String walletAddress = rippleResponse.getResult().getAccount_data().getAccount(); + if (!walletAddress.equals(coinData.getWallet())) { + throw new Exception("Invalid wallet address in answer!"); + } + coinData.setBalanceConfirmed(Long.parseLong(rippleResponse.getResult().getAccount_data().getBalance())); } - - coinData.setBalanceConfirmed(Long.parseLong(rippleResponse.getResult().getAccount_data().getBalance())); + else if (rippleResponse.getResult().getError_code().equals(19)) // "Account not found" + coinData.setAccountNotFound(true); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "FAIL RIPPLE_ACCOUNT_INFO Exception"); diff --git a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt index 346f7900be..cafb001a58 100644 --- a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt @@ -594,7 +594,7 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback tvBalance.text = html } - else -> tvBalance.text = getString(R.string.no_data_string) + else -> tvBalance.text = "" } tvWallet.text = ctx.coinData!!.wallet From cdc2a7f9ca0224170233e683ca5911cc4f72ba4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 29 Mar 2019 15:50:28 +0300 Subject: [PATCH 11/28] Updated on 2026-08-14 --- .../main/java/com/tangem/domain/wallet/xrp/XrpEngine.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index fda44e7931..4cd6d5b250 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -230,7 +230,7 @@ public class XrpEngine extends CoinEngine { return false; } - if (coinData.isBalanceReceived()) {// && coinData.isBalanceEqual()) { TODO:check + if (coinData.isBalanceReceived()) { balanceValidator.setScore(100); balanceValidator.setFirstLine("Verified balance"); balanceValidator.setSecondLine("Balance confirmed in blockchain"); @@ -281,11 +281,8 @@ public class XrpEngine extends CoinEngine { public String calculateAddress(byte[] pkCompressed) throws Exception { byte[] canonisedPubKey = canonisePubKey(pkCompressed); byte[] accountId = CryptoUtil.sha256ripemd160(canonisedPubKey); - String address = Addresses.encodeAccountID(accountId); - boolean valid = validateAddress(address); - - return address; + return Addresses.encodeAccountID(accountId); } @Override From 6fd0284a58b64df66c3fc940721fd4bac8cbc9a9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Apr 2019 12:51:29 +0300 Subject: [PATCH 12/28] Updated on 2026-08-14 --- .idea/gradle.xml | 2 +- .idea/misc.xml | 35 - app/build.gradle | 2 +- .../tangem/domain/wallet/xrp/XrpEngine.java | 13 +- .../tangem/domain/wallet/xrp/XrpPayment.java | 17 + .../wallet/xrp/XrpSignedTransaction.java | 29 +- ripple-core-0.0.1/build.gradle | 2 + .../ripple-core-0.0.1-SNAPSHOT.jar | Bin 0 -> 294113 bytes ripple-core/.gitignore | 1 - ripple-core/README.md | 391 --------- ripple-core/build.gradle | 52 -- ripple-core/src/main/java/README.java | 206 ----- .../com/ripple/core/binary/FileSTWriter.java | 32 - .../java/com/ripple/core/binary/STReader.java | 126 --- .../java/com/ripple/core/binary/STWriter.java | 71 -- .../java/com/ripple/core/cache/SLECache.java | 110 --- .../com/ripple/core/coretypes/AccountID.java | 188 ----- .../com/ripple/core/coretypes/Amount.java | 790 ------------------ .../java/com/ripple/core/coretypes/Blob.java | 119 --- .../com/ripple/core/coretypes/Currency.java | 250 ------ .../java/com/ripple/core/coretypes/Flags.java | 35 - .../java/com/ripple/core/coretypes/Issue.java | 101 --- .../com/ripple/core/coretypes/IssuePair.java | 36 - .../com/ripple/core/coretypes/PathSet.java | 273 ------ .../com/ripple/core/coretypes/Quality.java | 26 - .../com/ripple/core/coretypes/RippleDate.java | 82 -- .../com/ripple/core/coretypes/STArray.java | 129 --- .../com/ripple/core/coretypes/STObject.java | 489 ----------- .../core/coretypes/STObjectFormatter.java | 170 ---- .../com/ripple/core/coretypes/Vector256.java | 141 ---- .../core/coretypes/hash/HalfSha512.java | 68 -- .../com/ripple/core/coretypes/hash/Hash.java | 155 ---- .../ripple/core/coretypes/hash/Hash128.java | 70 -- .../ripple/core/coretypes/hash/Hash160.java | 81 -- .../ripple/core/coretypes/hash/Hash256.java | 146 ---- .../com/ripple/core/coretypes/hash/Index.java | 159 ---- .../coretypes/hash/prefixes/HashPrefix.java | 56 -- .../coretypes/hash/prefixes/LedgerSpace.java | 38 - .../core/coretypes/hash/prefixes/Prefix.java | 5 - .../com/ripple/core/coretypes/uint/UInt.java | 209 ----- .../ripple/core/coretypes/uint/UInt16.java | 106 --- .../ripple/core/coretypes/uint/UInt32.java | 137 --- .../ripple/core/coretypes/uint/UInt64.java | 112 --- .../com/ripple/core/coretypes/uint/UInt8.java | 105 --- .../com/ripple/core/enums/LedgerFlag.java | 29 - .../ripple/core/enums/TransactionFlag.java | 50 -- .../ripple/core/fields/AccountIDField.java | 3 - .../com/ripple/core/fields/AmountField.java | 3 - .../com/ripple/core/fields/BlobField.java | 3 - .../java/com/ripple/core/fields/Field.java | 328 -------- .../java/com/ripple/core/fields/HasField.java | 5 - .../com/ripple/core/fields/Hash128Field.java | 3 - .../com/ripple/core/fields/Hash160Field.java | 3 - .../com/ripple/core/fields/Hash256Field.java | 3 - .../com/ripple/core/fields/PathSetField.java | 3 - .../com/ripple/core/fields/STArrayField.java | 3 - .../com/ripple/core/fields/STObjectField.java | 3 - .../java/com/ripple/core/fields/Type.java | 35 - .../com/ripple/core/fields/UInt16Field.java | 3 - .../com/ripple/core/fields/UInt32Field.java | 3 - .../com/ripple/core/fields/UInt64Field.java | 3 - .../com/ripple/core/fields/UInt8Field.java | 3 - .../ripple/core/fields/Vector256Field.java | 3 - .../java/com/ripple/core/formats/Format.java | 66 -- .../com/ripple/core/formats/LEFormat.java | 230 ----- .../com/ripple/core/formats/TxFormat.java | 212 ----- .../java/com/ripple/core/runtime/Value.java | 111 --- .../ripple/core/serialized/BinaryParser.java | 99 --- .../core/serialized/BinarySerializer.java | 94 --- .../com/ripple/core/serialized/BytesList.java | 77 -- .../com/ripple/core/serialized/BytesSink.java | 8 - .../com/ripple/core/serialized/MultiSink.java | 16 - .../core/serialized/SerializedType.java | 11 - .../core/serialized/StreamBinaryParser.java | 81 -- .../ripple/core/serialized/StreamSink.java | 31 - .../core/serialized/TypeTranslator.java | 151 ---- .../core/serialized/enums/EngineResult.java | 258 ------ .../serialized/enums/LedgerEntryType.java | 101 --- .../serialized/enums/TransactionType.java | 103 --- .../core/types/known/generic/Validation.java | 15 - .../core/types/known/sle/LedgerEntry.java | 59 -- .../core/types/known/sle/LedgerHashes.java | 32 - .../types/known/sle/ThreadedLedgerEntry.java | 18 - .../types/known/sle/entries/AccountRoot.java | 71 -- .../types/known/sle/entries/Amendments.java | 22 - .../core/types/known/sle/entries/Check.java | 40 - .../known/sle/entries/DepositPreauthLe.java | 18 - .../known/sle/entries/DirectoryNode.java | 88 -- .../core/types/known/sle/entries/Escrow.java | 74 -- .../types/known/sle/entries/FeeSettings.java | 22 - .../types/known/sle/entries/IHasOwners.java | 12 - .../known/sle/entries/IndexedLedgerEntry.java | 56 -- .../core/types/known/sle/entries/Offer.java | 219 ----- .../known/sle/entries/OfferDirectory.java | 20 - .../known/sle/entries/OwnerDirectory.java | 3 - .../types/known/sle/entries/PayChannel.java | 42 - .../types/known/sle/entries/RippleState.java | 224 ----- .../types/known/sle/entries/SignerList.java | 32 - .../core/types/known/sle/entries/Ticket.java | 27 - .../core/types/known/tx/Transaction.java | 116 --- .../types/known/tx/result/AffectedNode.java | 156 ---- .../known/tx/result/TransactionMeta.java | 50 -- .../known/tx/result/TransactionResult.java | 299 ------- .../core/types/known/tx/txns/AccountSet.java | 46 - .../core/types/known/tx/txns/CheckCancel.java | 14 - .../core/types/known/tx/txns/CheckCash.java | 23 - .../core/types/known/tx/txns/CheckCreate.java | 30 - .../types/known/tx/txns/DepositPreauth.java | 19 - .../types/known/tx/txns/EscrowCancel.java | 18 - .../types/known/tx/txns/EscrowCreate.java | 33 - .../types/known/tx/txns/EscrowFinish.java | 27 - .../core/types/known/tx/txns/OfferCancel.java | 13 - .../core/types/known/tx/txns/OfferCreate.java | 25 - .../core/types/known/tx/txns/Payment.java | 39 - .../known/tx/txns/PaymentChannelClaim.java | 31 - .../known/tx/txns/PaymentChannelCreate.java | 32 - .../known/tx/txns/PaymentChannelFund.java | 24 - .../types/known/tx/txns/SetRegularKey.java | 14 - .../types/known/tx/txns/SignerListSet.java | 20 - .../types/known/tx/txns/TicketCancel.java | 17 - .../types/known/tx/txns/TicketCreate.java | 22 - .../core/types/known/tx/txns/TrustSet.java | 25 - .../known/tx/txns/pseudo/EnableAmendment.java | 17 - .../types/known/tx/txns/pseudo/SetFee.java | 25 - .../core/types/ledger/LedgerHeader.java | 109 --- .../core/types/shamap/AccountState.java | 341 -------- .../types/shamap/AccountStateBuilder.java | 320 ------- .../ripple/core/types/shamap/BytesItem.java | 37 - .../core/types/shamap/HashedTreeWalker.java | 8 - .../ripple/core/types/shamap/LeafWalker.java | 5 - .../core/types/shamap/LedgerEntryItem.java | 45 - .../core/types/shamap/LedgerEntryVisitor.java | 7 - .../ripple/core/types/shamap/NodeStore.java | 64 -- .../ripple/core/types/shamap/PathToIndex.java | 156 ---- .../com/ripple/core/types/shamap/README.md | 319 ------- .../com/ripple/core/types/shamap/ShaMap.java | 30 - .../ripple/core/types/shamap/ShaMapDiff.java | 122 --- .../ripple/core/types/shamap/ShaMapInner.java | 331 -------- .../ripple/core/types/shamap/ShaMapItem.java | 11 - .../ripple/core/types/shamap/ShaMapLeaf.java | 34 - .../ripple/core/types/shamap/ShaMapNode.java | 47 -- .../types/shamap/TransactionResultItem.java | 38 - .../shamap/TransactionResultVisitor.java | 6 - .../core/types/shamap/TransactionTree.java | 43 - .../ripple/core/types/shamap/TreeWalker.java | 6 - .../src/main/java/com/ripple/crypto/Seed.java | 85 -- .../ripple/crypto/ecdsa/ECDSASignature.java | 155 ---- .../java/com/ripple/crypto/ecdsa/K256.java | 103 --- .../com/ripple/crypto/ecdsa/K256KeyPair.java | 54 -- .../ripple/crypto/ecdsa/K256VerifyingKey.java | 55 -- .../com/ripple/crypto/ecdsa/SECP256K1.java | 42 - .../com/ripple/crypto/ed25519/ED25519.java | 9 - .../com/ripple/crypto/ed25519/EDKeyPair.java | 52 -- .../ripple/crypto/ed25519/EDVerifyingKey.java | 58 -- .../java/com/ripple/crypto/keys/IKeyPair.java | 6 - .../com/ripple/crypto/keys/IVerifyingKey.java | 29 - .../ripple/encodings/addresses/Addresses.java | 77 -- .../java/com/ripple/encodings/base58/B58.java | 9 - .../com/ripple/encodings/basex/BaseX.java | 231 ----- .../basex/EncodingFormatException.java | 7 - .../com/ripple/encodings/basex/IBaseX.java | 41 - .../java/com/ripple/encodings/common/B16.java | 20 - .../java/com/ripple/encodings/common/B64.java | 12 - .../main/java/com/ripple/utils/HashUtils.java | 62 -- .../main/java/com/ripple/utils/Sha512.java | 53 -- .../src/main/java/com/ripple/utils/Utils.java | 58 -- settings.gradle | 2 +- 167 files changed, 33 insertions(+), 12998 deletions(-) create mode 100644 app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java rename ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java => app/src/main/java/com/tangem/domain/wallet/xrp/XrpSignedTransaction.java (74%) create mode 100644 ripple-core-0.0.1/build.gradle create mode 100644 ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar delete mode 100644 ripple-core/.gitignore delete mode 100644 ripple-core/README.md delete mode 100644 ripple-core/build.gradle delete mode 100644 ripple-core/src/main/java/README.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/binary/STReader.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/binary/STWriter.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/cache/SLECache.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/AmountField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/BlobField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/HasField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Type.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/formats/Format.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/runtime/Value.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/README.md delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java delete mode 100644 ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/Seed.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java delete mode 100644 ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/base58/B58.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/common/B16.java delete mode 100644 ripple-core/src/main/java/com/ripple/encodings/common/B64.java delete mode 100644 ripple-core/src/main/java/com/ripple/utils/HashUtils.java delete mode 100644 ripple-core/src/main/java/com/ripple/utils/Sha512.java delete mode 100644 ripple-core/src/main/java/com/ripple/utils/Utils.java diff --git a/.idea/gradle.xml b/.idea/gradle.xml index dbe604a60c..da117a274a 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -11,7 +11,7 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 8e44652cdd..703e5d4b89 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,41 +5,6 @@ - - - - diff --git a/app/build.gradle b/app/build.gradle index d6bf56e099..dff789a723 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,10 +44,10 @@ android { } dependencies { - implementation project(':ripple-core') implementation project(':card-common') implementation project(':card-android') implementation project(':server-android') + implementation project(':ripple-core-0.0.1') // implementation 'com.github.TangemCash:card-common:0.1.2' // implementation 'com.github.TangemCash:card-android:0.1.3' diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java index 4cd6d5b250..d79b9ca4cd 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpEngine.java @@ -6,8 +6,6 @@ import android.util.Log; import com.ripple.core.coretypes.AccountID; import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.types.known.tx.signed.SignedTransaction; -import com.ripple.core.types.known.tx.txns.Payment; import com.ripple.crypto.ecdsa.ECDSASignature; import com.ripple.encodings.addresses.Addresses; import com.ripple.utils.HashUtils; @@ -26,10 +24,6 @@ import com.tangem.util.CryptoUtil; import com.tangem.util.DecimalDigitsInputFilter; import com.tangem.wallet.R; -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.DERSequence; - import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; @@ -364,7 +358,7 @@ public class XrpEngine extends CoinEngine { fee = Long.toString(convertToInternalAmount(feeValue).longValueExact()); - Payment payment = new Payment(); + XrpPayment payment = new XrpPayment(); // Put `as` AccountID field Account, `Object` o payment.as(AccountID.Account, coinData.getWallet()); @@ -373,7 +367,7 @@ public class XrpEngine extends CoinEngine { payment.as(UInt32.Sequence, coinData.getSequence()); payment.as(com.ripple.core.coretypes.Amount.Fee, fee); - SignedTransaction signedTx = payment.prepare(canonisePubKey(ctx.getCard().getWalletPublicKeyRar())); + XrpSignedTransaction signedTx = payment.prepare(canonisePubKey(ctx.getCard().getWalletPublicKeyRar())); return new SignTask.TransactionToSign() { @@ -449,8 +443,7 @@ public class XrpEngine extends CoinEngine { throw new Exception("Invalid wallet address in answer!"); } coinData.setBalanceConfirmed(Long.parseLong(rippleResponse.getResult().getAccount_data().getBalance())); - } - else if (rippleResponse.getResult().getError_code().equals(19)) // "Account not found" + } else if (rippleResponse.getResult().getError_code().equals(19)) // "Account not found" coinData.setAccountNotFound(true); } catch (Exception e) { e.printStackTrace(); diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java new file mode 100644 index 0000000000..1d202c922f --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java @@ -0,0 +1,17 @@ +package com.tangem.domain.wallet.xrp; + +import com.ripple.core.types.known.tx.txns.Payment; + +public class XrpPayment extends Payment { + + public XrpPayment() { + super(); + } + + public XrpSignedTransaction prepare(byte[] pubKeyBytes) { + XrpSignedTransaction tx = XrpSignedTransaction.fromTx(this); + tx.prepare(pubKeyBytes); + return tx; + } + +} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpSignedTransaction.java similarity index 74% rename from ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java rename to app/src/main/java/com/tangem/domain/wallet/xrp/XrpSignedTransaction.java index 56440a9bf1..29babc095b 100644 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/signed/SignedTransaction.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpSignedTransaction.java @@ -1,41 +1,32 @@ -package com.ripple.core.types.known.tx.signed; +package com.tangem.domain.wallet.xrp; import com.ripple.core.coretypes.Amount; import com.ripple.core.coretypes.Blob; import com.ripple.core.coretypes.STObject; import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash256; import com.ripple.core.coretypes.hash.prefixes.HashPrefix; import com.ripple.core.coretypes.uint.UInt32; import com.ripple.core.serialized.BytesList; import com.ripple.core.serialized.MultiSink; -import com.ripple.core.serialized.enums.TransactionType; import com.ripple.core.types.known.tx.Transaction; +import com.ripple.core.types.known.tx.signed.SignedTransaction; import java.util.Arrays; -public class SignedTransaction { - private SignedTransaction(Transaction of) { - // TODO: is this just over kill ? +public class XrpSignedTransaction extends SignedTransaction { + private XrpSignedTransaction(Transaction of) { txn = (Transaction) STObject.fromBytes(of.toBytes()); } - protected SignedTransaction() { + protected XrpSignedTransaction() { } - public Transaction txn; - public Hash256 hash; - - public byte[] signingData; - public byte[] previousSigningData; - public String tx_blob; - - public static SignedTransaction fromTx(Transaction tx) { - return new SignedTransaction(tx); + public static XrpSignedTransaction fromTx(Transaction tx) { + return new XrpSignedTransaction(tx); } public void prepare(byte[] pubKeyBytes) { - prepare(pubKeyBytes,null, null, null); + prepare(pubKeyBytes, null, null, null); } public void prepare(byte[] pubKeyBytes, @@ -87,8 +78,4 @@ public class SignedTransaction { previousSigningData = signingData; // } } - - public TransactionType transactionType() { - return txn.transactionType(); - } } diff --git a/ripple-core-0.0.1/build.gradle b/ripple-core-0.0.1/build.gradle new file mode 100644 index 0000000000..31be8312e1 --- /dev/null +++ b/ripple-core-0.0.1/build.gradle @@ -0,0 +1,2 @@ +configurations.maybeCreate("default") +artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) \ No newline at end of file diff --git a/ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar b/ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..0600aabbdbdf9d9af603a1a0e36a8b640acad177 GIT binary patch literal 294113 zcma%ibCf4hlVw$x*=5_dU0t@-W!tuYW!pBpY}>YNo7=O4oo}?0=VbnM-+Sj|WJKH> z5h*VP0tyWT1PKXr9Pcd)^!NJlPmjMB)Zbf1L|KqlLROR>1W5iLfOWn0i z{`bp7&8>`;l+_%}os1pm46XDX9ix=3<>uuvc$=}E&bL5?!SASu*4@&G@;ST$#aS>B zaC>mLgYs(8?y*K0paafEUz6Uh;0-J&niaBG*B-WZPW~z-c{YR z^Tk;@)hUtyLlpKio5rgnt>GDJO#dm;d8W;fAJa&y0ooGWCXK(@=D^k&=UDq0AM0MX zD2g*)GR-fI*OlAiqOk=G1K z^tHM$-gKA@w`ZZm%!Y(*;>Jg+pD@uab^o!CeiBvKfg}1ug6#z7gD|<>vD8My#_S$c zhij9@KU-+!J_`9L!MZ!{(0jSmJw*1Y^x4-m>h)#x}z0lmE%!HKXTg@ zHgODiRbtCqzR=mk1G7`_V4pcLoy$*L#@GKYEH8k%Lo7q-gdhq4`GyhIDk?*`c@7sT|u2(_=_THz>IWim9bn(K`G~%{6dc}R6i1ddS78mO3m>A zgZvspjcu{`M4IbnmkW_s{wr2hfiZ6nJScpWV3&t9NKyzUvT#-4j5)C;6wfyKC5@uxAPE}VIS7)O-5$1~y$0Kmq(QqZT$5$%9%LU0yu_MFrC^i#?qaxK0vqo} zp{qyp>1KnBM`6`GnZW*%^EF%N^}FQt`&)@GtG6vFp?7ka`pZfGF>`&p$M*A9N1FRR zVEFraMFc48B_S_l)vYL8 zZC3}iX2?>x1Fc5s)}upk5c`%4)pp3ca-WuJE4;bPje9F^FUu_@+;!gv^}5&d_0*f@ z&MzF|*2jh~cQ5cIHaz4;9~Hk>Z1u|B22b^d5e#4L26Ej;c~EtNDphGV$X)do$_7u# zPB7O&v3U+aI)f8cLiS75z=6p;XpeFna`reVTRM|fR7e|2soCTWch(#9QZ5zh-A_Ps zhIx^PWanBo3hReuKGgilq;w?4QZ8S7A${YlvX&hDY0#YKRlzo%Tp<`6Jrm>J3EUt! z1g!UheJLFVZ;{+-UZG8Nut8H2!!S-@m%U+nBmJ8~?pa|{I!C;okf%`tLtP+o*Z=9Cxy8{k+y8@bG!undVt%+3IikPV`j!U*X*E~5*dd~Ib{)KQ z2f4sIZAkg4ewu}-BgebfWNnMDAICY{wm8SIEE1Kyu4K0S1FAkyEgRtCB`HL`X78r(QkUA0hY7>br0Ru^NEh?74}X~{Q~_QL;XVatgCe6 zeAS(|ld<6|)!W?q9UXA(@XZUiJscT;e>46Q^&|8hpZW#rnP26G`O3F?2OY~NO!s!Y zhIJ!=9OXl_-}aUpu6r0CIM7Rci9dF5srOVbnJTz9S8S;`nPF= zfLaR(>j%j9!Od4h-4K&%B!K0sN+0XN3C$IfuVbw+sHqysRQXKrRhDtJ~d5 z=dO-$MiVb1cw8#%GO=c9tSKvetUJArQQUkIW1m=Dg@bbZ}(|?m%&+Kgd=(`sRojX@4{V`A=H@G}$>i(5XF071@&&ke>=d z!Mnn_+FxoK+#b*w8*B0eOX-CDGRi%9Q!8F8$c_Kbh?Pz=6vDAALE|Q~v%N`O_G-&K zUxcPt(ZX%==z3xOsn7hw3|QcPY8l1jx7f5(Q7)UXt(d%^uiqLI#O&M~1r=U#GxSBF z3#-?Hj)W0NdDyy$?W2adlOFpH&mYy@lZ%Pd3&MaR3!E(U9qw5!h;HFW6%serB?Irc zvvjaU)|EhpvdUu1nMTe<{XNjfH84=whKT|P__0^8s-!8~3>@pNhZ4&nQ~wzd9vAJs5jH!B3Ksb%((nB9Mka#P9=53 zD@D>ogq-lsJ=W;(Zh}9ZzaF0rg*3Ce4Q+E92^nCZKNg?!>Im(=GIe=g4v+(?UU4kX zacBckF85c&iLFU>U1uE0H4J{T#chaI5{~yL8oTeBc$XE^y203x+S-5|%WWsL-~fY7 ztKQ&%wGnhLf2KfE@gSs#*>-wPG)ok)LkmsW+TFJ$+76E5;E&w`A8pnufI^_{Fh(Bl zILc=Nu{2H?82)6ZQ8C|_663IYnaOaQ`OnaA7Tx5*_in45BjI17P`bdjT~1h zOT!w5To8FQlSmVoYf3gj8cc#+?+2NT0B;sPrF1-*KXa`EUK&Y%+xcn%h3DM73zSUf z<-zdNQvk$cbdiL`^h|NR8Pj~rkEVSQDOI7V2q5cjmQ^&8k~m=iOJ$zD+^);9box-F z6_p91*9hvQ`KfZ|Ag)8#>f|=%;k8p?_Pg&ta*xBYFGHBWq?`fv|HD20Jt@ypwN^t` zL-3&kUb0Gd6%-IO^B#q%tqKnrp5|e8HL3gldOp?#s@_pU^?uRn4G8Drf&SHRh=-0&JqF(@<$tCHqx~Y1(_-0fq*U(ZtSKj>$7SNiX$H0Q!JNWamT+##QlcI0fso zQlmYFYfK{QB+tyxVEgp4T^rv;lqG>fzoFEA)@*=RZ7tp9?WoZQ3dEY)?GSiYaPHZY z1Djf)`jNbvOXMcB2$flrl!O#Mp1msy`eu=gvUue~%1g7B-Ds2i6H{NQHyL1haqilZ zw@bWnwEH*fvVQor0HC(M5T{wC@6O0SDtFM~?r~<9yl-9?%F~KzcwIA-NoShGJkzfi zY!h%jJ)e)LaZY$Doo7FvgJP~cHY63!;5*CesDWA}sxz_$hqk-$C*p{JGkIw2FbaJy_}=8Mhc!S? zGW_T8J_@jM|3p*!nV<$p1r9NE(&lE%`chGuld!(J=^(!;XvX;E z-PeXN*$_(^7~z76R;2~?kke}vnHcGeMVJ-9IH_)8vx5#&Kk)xCn*J4U|5g%0`!AH7 zp}wKnf3B&xL?iZh{wK*^X=*@Lr)bZ(MB5$I-NBC~_XVOSQANV{BE9X^ zHHtKCLX{Agj#_=lU}oNSJ@PVT`h2<{R|BF}mmmylB|%D+W2B)-R3$73i2H@s%7M1e z07k@08B4FWAvE92TSGP(elEq#aci{6W4F;9t#NFiq3T-HeFge8TJCrCdS`aOLdmJ( zPE%`FpcRZJ((m%avEl%9T#81ztPd?kpo7YiDOLseRy6m#>~f_yU4SKP6>SFECTZ+# ztch5c4c@h|+x(KE3dFeCV6lmITlM}aAMIk*c@DjDEE`ru(P-4ZP`6a$vF$+TsaQP8 z$|iBSzkHRy5oK-rrcyxX{P&LbTaMP*OalCTBI#yhY?rkMQOjMoDRC_o1U*g7rD*<{ zjl0Sjx|_Gs!}sZq45=m;bO@epweT|g20%AXL^Esietmk-`+Q{19tMQ#ZKh_QkIebx zWOlaV7xbn*&&(}?lsyfM5my)9R`ed5Wpce`*V<}Il7L<{@h8eO&-C44F?HFWy%r$Cq`_?FEy29fZG;t*I6qBW7jlm@8l0+v{< zq~Vb^QD;(^AZ&;iF@|-02YJPi{o2Se9m1!d0`Yc`$w7LkF?}2Z3ljD!S=*ElSh)8O z`ys*dF0tVL1I$5$p%OuGvrQ< z?8sZwG}=nsURFG&kfXZ)=s!W(pWNMly#Ng!2#DnW>k0q-`8TRrDj}<3_{h>(A+bS= zE7bnB>I?!Z7PpR59+)pk;{Yqxs68yEa zFS3#cPI5*+L9EQvo(|8c)#r|BPxmQLHsA02^=qJ~{St&Geer%fNIY1uTPo3C7=!Ae z1&)NE_BvfHx%yhNfP;g4uVFP`eZ?q za}OqkMX5;uD>zIz4S)HZxJ)Lwm1;*N0sLC)`BN$E*32~I8}dVLf0bLQj;4zS&=iS*W$#JG&`tiqEMo*C_G zas|WwTja6EEGc*wd_pUg7-P*VL}1%OW9gpd6p2~?DEo0XI#&vc5OJET&`7C*{!b-@k)#5A{29X`EOj#59)`@cerUPtjUg zelseLw-J;lM33^ID0F~oHL9Z;R%N+%YxF?rQgv5SiaUIzy4GVfv%qTK0J9!1g zII~$^eSxsrT&S+5R{C9lBNyQ}Wc zP@SP-%_y3zk$`}K(wFONqk z@>VJ?N@1(j3bsxCBAeh;^G2U>ANj8g%D(`?-jmPbCj&s#g%H>=*Ri)s+CN*YZ4YGsxc!jEXJE1;56GrPP-c9i$(L#a_&fOiA$?D;nZ zoY_ljZ0W9OH_(V(*g{tUdm`@J@LSxHZRJmMeV+C3{k|LVQGduyVLr5eAoO}5x&iHd zC*7bjuF%zIMJezA6j8T#6dT!6|HdYdPMLlihGe466EtqL##=mIORlt$=PE(yF&9Ns zTgrfWms~oJSOOV{)A8is3l$Q{ggsX5rd(?S@~*v<3tGb?@ z>lHt5^GeLX%hSmn-#+mTQUkrpmx{&$&DL{NQ!!lRX>u~36_r8bnZbyKi2}P`Y$@xU z6$9VU{MZ+yjP5Kg#v#QXPECS&u*+O+52bAp?xwGgSF=M>(;vY{{7Co%uTY<&m5gZN zwO;Cgnd=i|b!I#PTaXBqFu^rM(9c0%BWjWl-+$**2=P~{;0<83O-xz8fJ97aB>`N` z)%yJaN@w3Jwc@dQuP|`-aDfvPpo96+d%q>|piO+@w%&5)m4qb|#o4t40tTMdCyeqWMp40p7DjIq6px70C`iG zUB#Mfhj*E3J?1;+obG(?=;G}LTIrWWQkbBKWuP{c9pVwHtjTC4>z7=teXu?pduF?xgK z!dD=Xzu06kcEAmd770{GO1#(#}hDC4TuDc86|Z3P>LDx zViQbWboX%oG3j5O%SaymwOR=T5D?4%(sIfU`ZkVM`cAh0(k86>%YhdJP`&`2iB*Tu z=eUPto`TRnr~eju1==Nwi(S!n)NII>Nm*@MJ;Ivi^g9y9-8k)* zVOvJ9jk|5t>4bD)x?yoeQY>xR+&C#z+AYzwhifHa9VaOp!>KlV&V|C*46bn)A_3Cl z6-I&UWPP=dVYv47XEK5jsgd6s`QUbcx;6?^N0t>!Nxu3JwmOV|B8e0j**Blb3+m{K zl2J^Nc@ipDp^L1CyDZK=I19nbntodS8pzK@)5r_YLXz_hezkVI@Q>nDsDL$qQ(`=EMaOL4iFi%*+ZOJ6wBdMQgU-Ym%ZubcGf>ol1!ni$L zbP9$ISayM-el)5Ei+lixNLc2BNo?ecc$UevPV)?lWfp4-^mQt#=sB{}?Be&XYtM|U z_vDAncRJ?&48$RNpPc9H=Pk}}-gVw%SUDc&Q$(QU@K!FTjLsW6X>=;nPv z-0L2pkKL?}4yoaOw`M@X#0?&#*yL%))|Jm^H&8?!>j~t^TIrEo>XeyqmpE}SdACfh|GA+dp~~P zM^8mJwUPN3$>go*&A|VJ6RFgrFlmoq<}n%!bk38fL3GAywk2x#w5|%lUSH>SZHQ}G zoj269|B*iHG{9p4PHfUZzjC#*YleTD%yniYrKiI8qGGNhp`~;UmTU_345$*9102Zu zkfr4(YmV>%f4fj$1r-z{M~i@kWAERBcGF!kT=GRAJhD~LBQjoYE-{>Hq}aU~y1ZbV zo?b_$pO)-R?wYNv{%Y|Dd0c!4^;$RJedy|-#A!@N4%|%M)OQi1aS@;~5`9W@NzGZ5 z%9+O}J4SK-$$fDd0P^_55t4FUBeLpw?T_HIhMpk-gixYqjrahNt;g#=hv(vczm)GLu5SvX1)pv(CCRGZ42|-1 zPo+{!(3r0O%ObV3h?nPJAOK{^j%TIR?QW@BPfuL$Hqq|KycYZ5e${6a=5Z#5qHtJb zit(d-?!H698k;C?Ma*RvA9K)|_0}7dI1tUT#SdBy1D7smT|}luP18wYyGppE+2&w zyi*j{&i=^A>dE;0%dmCAdI|*V_~j?g2q4FTK^F3c4IxSEylElY$1+DcQ;~Wgw3bU% z+XtO!t;7nVHpM%|)h5n$?SSLgJ zaNW!|o;;MbBrz~%JE9kC2z~gl54$l~Uq(CAEt>thu&{eI;9r1lY{>mkf8U*)g&6vn zG)S>5J#y5bMoaZ+U(6SFkk8>B-&=l=Wz|~?CSqm~?N7#|x8v-_tKl@uHm;1VWG&suyf~!{p@h34^voHv-r(^`<$t=xEyzk?Ao8C1 z6{ZmX9L6^cWp2lS2DenBBUj0rtSLn8n50)N=bwpT!C=@Nsl?LQqDLtPb>T^7%^z6L zD^kAKz*-Z{h}oA<`I~uhkzp}m%!;jyJPQBU91n!Y3p9 z$b~egYi1&@&|^B+I$H>Nda7MtoLg;z8kLQZiJX|Ui3Veeu55^9u}$=kWo>=_X|oC$ z_s6>qQKY7Zl{QZOI$C6{yf((?^PNJ>vr(*5|0*?-xC&#H!};>EyctsDRDOw+qa3u; zahF9DxK1N41H$H@#hE&uVGO&pTe?K(>pF>Grhqi#(vr}!)4uDvnHs1sQdh4!SaHh- z>9o6a7~VjsRxHUmK3$&07C}z+I96jN&RG7u-yW?uY^ukZ{pix*k%K$kDt;d4JXc!6 zllyd1o?tPk4JmiR1g;iR4z{YE5o?-@U22!s7Pe}hAsfenHx0ke9Z$>ff+=#fYs#u* zerXBxVtP>Z`1p`_E5{uuIw7i@I_!~^p({b$@bu|-1VY==-=fT2)s%Jm^`)a8?@EEl zCgl8}_{I7XgAMD^IG+9Eky^fZ<>m+1-_E3I&wcY)x&n&KPag4O5{1klm-MIj`G+Eg z{lX*?Y!Zm-WOB@El5F}-b4eWqL7Gj<7wsDf>~W~726I>sHEX!mgN9+!^U(k}Ogc(6 zLMqAD!bGxWJg_#|(+hk;YcYKua9%id8h-0B`I(B$iCEu-wO+FpZft$Mt&`Lz_TpkrfH7wT?!MNhjG{GdeIrL0b=H)_{w)8 zG}pWz@&G#p$rmuUJfvzRe=?XO7X`oLIR5NIu+ynf8;!H8q+OAN--Nq5l{-xo9NK+{ zeP^B0_APMDQk5w?@WG8@MYoyhh!egT#vM@xy-;Rd2{)+OlG?iHFXDhAN0eI1ZZuVt zt)3bB!7L3r>_HVBxDbc73%ZT0@RSO*Fwagjk3(e6eP=l;9lTc&omWH7!|OqBNgr(c z`sa^E67NS58alsb=xx#WOU&pgnpFD!@uJ6?9%|Gb$wRnp$m&}vM^gY(S0YnQUq#Y| z;36X0LbSms)XT8^qBF1*epTMF@q@2BlD|`)b7OmoGy8m+i_v!CKAYf$BwH7C?e z%u!`7slw&r{XtMJ>xfkG{WTM5hwA3*9OJ@GR?Xv&%rPK}LF^m9hc9ehxi7#4WN&*kX2_By3T7^(5KM z0krWeTmjf53a+AW?%k2mIZMGtlSEWiKM|eb$L;Yd7{a4k1b8_mvc8Ct(xgzL7!~h> zST1Fh6I(4%WA~jT(-kf9K57oW|B=YO&9|Cc{*|u7e?<_*|15y4|4F(2t8NWe)Ry`o zh{C&HU0to2?(HiP{L^9v?cuL*h4Oz?eCet#kgaU5Ylr@<2p~Gi!=H(XzpBK>@aAA} zyx#Dt_*i)@3S&|c;YDcXG3B{ zQZFC+O#TV*n{Rw5h~nuB0sc90-^K3KKZkfK>FSQbYO+G9X43hq`w`GJdH(BZQq~Oq zswz&zfL?q3_Q$SEjr+>|8WtO@mBF|G5+w*$6XuhN)EgLzWhy~e!;}G$`;t@dV5RLh zHSc0Fp8%y=I!7U+yg89NA3eU9PCyfY1%qj}kR(4;XVVwBqKoJjMc;`_DM-*DlI9ig zKxv_;Q%4x$HK7-u)N1sId2#Fcr>{6X!TwJ`Fr-Qkkp`-i`jD2eY&xOZ8}dIIESwx; z()q8!`u-Y>^?ze9c?V-db4PPq8xaSGf0e9BasStPfNcfGdtzEC>hnILk%iv@xiCVI zjF2Q${qOeJRtB3%tE^|H&WM8OpME~dP9}*Y(1jUk&tAOuct`v9m$*HMYzd)xu>vR+ zXiKyxm^7zt`P15f%clLGR-_?9YAew-Lt-y1DE{7DH)1;KrlC21nIs&*tJQlNzva@Q z#@6*0X{V2O%{YSPTXO*6dUAFP2As#Q&6{kgG_7^lmi0r)Gq?E2U{@x+5iP3S5rH=y zDN0?&!f9T)(&F(z0r^k6;>N5TP=~P}pGWjDu*1F_Ih}1=v{O+g;w~R?4g+Zm+=WB9 z5LoGe;8&I-gyz~_z3+K8A$yC<^fL#7-!ah`fQ4T9^x%FpZ|lge^rdAoaS`!2axP>P zR*L8u+!|%w-fS6O3DY?vSM%aXl(N1S7;_`w0<=FyrDzVwOQ?^+r?Qx;MNa`ED5;D^ zRKS)f*Vty}8((lTGP%EL=aJXe!U+$|butWC{s6#8y8go~wVxMGUf18M1M1(YY{vhM z9sg6=LCw+*TMhN=>g>;)$K_ghQf?uO%^q8wv6zgtmPLvE9)}GI4)=oW?_pXuTH6EX zLhV28(6SWf%-Uf3sivLhb9l^I*y<>QLi^yzK0X)day3^o`_By;g%0dkcV>b zQ|p3=T+aTEg?!rX&L06l>V<$0txpjIM)#%9_l*c;@1@*V|B@OMvyXJlN4S?jl$}r; z*uLq1Eac`NLl3w?!q-i%&9WT6rIeMH<(nKe<#??Ooepc6K-j1`P51WeMZe}6+~K#P zDTQ^7v~1&27@4d%YGBGKN*ig3Q>`mOQQE)WD%{ptpaC~uQ+A@RSOJU@lsIX#{xn4$ zS2VA3<*`19FHW8|T{K!_&^E}Ku28*`pQ1Q%IZl5e#qmlbm1pzG%?VD{LF26QK3bK`Z@5_`qWn5@*qTw7Zt&?!aA?E z7`|jaO2Kepbx^Fc#>q&}OwH6)oNri%z;-ZCO*@D;J{e_IVOs1>=p^RAW?9W`yd&!pK4}Dn1 z#4Tf=#|y`0GT{!W zTUkl8SGvLw>)Jr(s!yj&3UgC@!LH1r_jQG3fl+kb<|d zrN;S+B{Xa@)3UK_>;+O|f8~t1JEN#F*X_}3Gw$y z>b|3`A|km-xTiaiZ3<)H{D<@JA)L||a+|zKrFZie0n8^BH_ozZ>z1qqGijAPZoJTv zHaE|;MtA&TFUt;s1?m9QC~sGg%go(@%UjJ?e}u>q6EU|x>v;Gz$vHxlU8&J(-+E?7 zj&Q)7lbsFp8Ly0IJO#yZ&Cx0R*e(O6Vv5?0UFrs`x%PqahelV#7TNG^ygH4t))C8R zbDHJSN}HplPZl{H%@%*E_eg%r+$4sgf)}Zpu~R6gtv<+JI_}jzFHtdiqs@|G;+3yP zoUL$)+Uodj&F4}W=NZUUj33N3m#VY&Ij2V)-j~ZZH#RHgZtPenSLQk2vHrA>>5@fN zhoiYF?k=ReDZz|%1j##9xs84x_%%l^w_yf+4ey4B!_39wTQAC%h0to|-!o;t&|N4MJC#ksEc8^bB_H)pNv!*&8z<~DvPoak0tuOL_X4O zNirgl>40>gz@s`ifqOprVT#PWu*%Ck9WUy4O@?Srn}6v>gp{XGgt+>vKQ{-TQVx)f zv}X9Fqx#EfQZ2{;!UdVA)g198M;QU9`?GqmZrf&J&;E|wfIT}`8l7U#bx(WX71EG< zOC~dC>6E%(=n)WdMiHXYr;0^%RT~Tran?k%wU>XG36tuWq1P25FMt5$7|IZWh)QyS zl0HK^a)O>teS=TC&mZny2(>C(j@A$VMYk7%^YIzv+uKWjbItnmJK!l~we0ILnrNy)R+V0iBGy$r;EicG!oj<2hMeFvwpJ%x8RNS0Chhg^K@V!>9 zEMZ(HL)SGZ|HFTngw(HvON7A(0#c9z0wVigkb!@hKKKpgrKGaN|6FW6_s}S#1f7Tm zSuq1t6zUglMoEj(E})ql@Oz%c8pK*LA#u=q`x#ej2uuV8HKGs|<=I=*)M=yH9&^|p z-xXJ^+wrR1-QC+8>X3c=rr~9)Xjdke%1j>9qs-jMEFjPTC=iC`((kT zSfg<3!Q~m)DY2lr@W$5IWf;QXnR2!zC3a@JaKnd+FMpet@6w$TYc5mg~Fg4`5fOGM?4z8DpQ~M*d^310yo?py0e&wIa@R_i2@t-^ueNp zs2@JXA-Gg};8(bJVVB9OJDcK0ucKK|Lbw(cK;9A$Rp`_iL!n=RCtI$D_@vRV^jE$p z5^H$rtZ?hxt_~l7E2gN;-i0q)PC(>E*n`(ETtby^btvMZHlV%AD;!rf&mCy8K3uL5 zcoH|qBrxYhLt0?|vNj_{o-yzYzR-Y-6-O8?Rb=o2mM;Wf8ZJcMo}zK82+;p`F4_ZM z)&oC#DrTohm2Z1&d;|a^e&9ewRjMvNNR-~@YSj@xQJ=aK-Ed3gp{k@H6tJN9Cn&r~ zc|k!zP6ULorEHstDj9hQ8e3O_K8mdiI&IFXy6LW<^wbQSACR7I^`Y+JQEJv?PtU6f zIc~aNRVahK*ih2%c2%;>%GR|s#61(?M&1@X#v~vTo8BJEH8mvUk{QLYD{R$~!BJg* z_vo@R#lG?)O3lxgmD3|vC`-QjGRks-g3Z4;Bu8AIWwUR(@{*?PnVggpb+#+HcYNbm zcEn@g$k(YOun;V)Exa%&to>`DNLX8R;ZRsxa3M)pTV!ETSX*eJQP`Tuf>~i1(V16) z9l@Dc!I$8SEZ>Ig3@zV=)B;AK8PT~t$+q#1yV46A#8YSl8Pe5_s22gGhza2)c#Ml@ zx0Zf_z*1u5_%Y?GKQwc^0(re`nIxy=JG;qX+xg5pt-Y*lC_A4J8oc} ziY3oE&tO)zxaX~x@A?m%tE#-%h&nxjy>*1%X!pe; zYU+v<6?T;+y1yH%>8NVxYH0TRsW6QU*zAUqBWPTmo;+zV_;6ythQXCmT9<0+Y$@xi z{#KE-HiyMoL95W!`Q2EVSx#jMt1|VP#9HJWC4;I`1d~B^9>yF9Qr^)!wHMo6QPHn< z0S8zhs{1pJPIvVLK{Pl{1rn#htg!b7u*=#wlIxW>_Umw<=eMTPRzsZ)l#ARCtu@RG z_*hiMOkU5d+_73)3o$*xJV~mfS!$JVd<;>|8s@Wa#RirGD(u&yaR+ zjws~#u${+v*d!Rp3S{f3KpycoHYYHUE&)(N;yJ_E!3A$BX1*)k(9~kpbo2SMXXl0i zQI#2(r{<|=C$}Fu2Z;)Y*AHR_{q^WCT=K)QHKeKuTRR%(FtoQ;u)`<8U66B47|h>uaReWjBPSja%quWlvT;#st6>pTG{PzCGKkn;PqDl1GYXL8*uOwiGSdg0ev~ z8EXh#Wh&{aOU{IzRdm*L`NBtxX4ytvRN%~cf$3$VD;wL8mJE*T*;old^}Q;DC1oCvB>%TjX+ad2^Umih`q;E)Fu+V?fKTiRp9e;9Q9ZO zlfN6sDpV1#%O$>R*cv<*)WEmCTR#S-(Qc|zmUw9p`&;bKi3xpkCkux-VCt|+YWenV ztE--z!Zb=?BV6veFmX2BgiuZ~aMB@76vEK861?D(R3*Iu?+=$GsWQ}6M9;6 zh)D}jo^rBl72iiej!Kl08!&YS8DU(_EzU!U7uRgzZE^!1hk6J%E=nCWOHF}p+O19W z2dwYwu~jvb=zX{>TdsbT#^eWyxcGGhC>MR9EJMw``%wejVUP<u3GFOJiBGc@xhRsr$#stCCJX=$U^-9Gqv@Oq2r{@fJw`@8n)HYq_dSf zI2~QJLPeX#(~*vGJa+&i_6ScdFc}dwze#Au)F~IdPK_z!E zBMq2ai)p@K+3joX#xx{QgNiSR+u8GymVTlq9HEAg95532=e7 zn7DPpMCl_qF{lWVLk;f2y7}=I-}_GR>81C zNGiL5YFq8?fJ487-&o0Tg04mPnk7)iw`zg7^dJf`B$PseaStNJ3}-ckO;dJgHrW(f(sQgeoWVIbG;If{0E ztZ)la4heiel5$ILSu`F-C30=0zBuq)ih=#P+xdM zo57VyFKWmszRJETPK6AdVW9}4quNg=QR;OXh)P&<2FyJaEYE&oMYWOR!Inry;%<12 zcW&?TPkny6#yJ53jNVVE>Ekt0KfjomJSb?GQm#rNlek<+NJh5`{*}$0b-z1f@$&q3 z5N1YCl2T8oP#O74(+E(*!1)DPGdaRK$zu;n!>arVe~wAD`hFHzQ0s#S(s#c0r|$3E zAQ1t&^Rv5P5-qxH5X*Mr#;QGD8hXj-^=T)c@A*Ujx*~vi>)e_m={Qndb){y$B%l>> z6RNVlF2~MUUhlDat_xdZ$M#+<9v7UNQV`B*_K8JUFWenjwmqMBMV|-zOcuV3)F5c<%b})?j5p?}m+ZoU!A^q9j@TE!+!|GJ-2+I^%j{$`&fZS)hN3XXB zh`O2S@fXpq?DF?gKqC`I5)P#xAguW51D(9r+fybi6}?NJ3zbxPB6qLn;8|)-FLSJQ z3*NmZPA5k8Aj~Pmj%@j-G1*zHh4zX7!=46ETnM|w_gx=7Q`{hbRNi>* zf?y@e4BAl*X}rP*XH8uf??pzIn1K?LO~|FA3Fr17c9SB6NP5Kv40F z&2&|Jn+J~O+5b9redqp7p?Vlzdvq3F<*rt{SahSaB{m3h@=WKuvWRx4p9|MYlv>)x z08>m&gFd9#&(M@K*;mw@0}LM3<4SD>pOM!?e^b;4y=oN9JMd%x-V#Ghy-J@0yaQz> zKdc%&X&gdjg^H@-71IYV7|tJ>Y!vdx9ojeaTIHpGp)FK}sxmT3@sEJM7=klGhVh~6 z?^j}I-$Z^#aT;S#T!De!dmbz610WdfKpW9ssW85#02rw zGH74u_ul0j`d}GTQq?aO_X%cb&52~H3p6$Cd- zTeOJCMW&kKRga|bWt1yMovD768f9`JF$1g+ZO8pF(*%3s`&g%rk}sE$9m>L zC^pHr`i7q4mGm3>v9DUGc=)?mMs20wf^j1N6hU=Y^(d9O^P3;*gLP?|Wx>!#>lb86 z0)5-_J_sObU-)AvTXhBbLZWcT6->szMgWC49C0vgPgo?(X*Zty+se;+JgaaX$kDVG{d5~YS(9zZ z(;k^F1CvDl4`c5f9ci?!d#7WkW3yx1wvCEy+qP|69XsjRNyoO$N;*d0>~r?HckF$? z@7y!iJ8D#oQT5lmYQAgE`OM$rbKMBL^V7EU-AQObmDW_vQ{hNe_B>8vZ9mlQDggSDp3S^1S$g*<1uky`UR7&TkNkh|^s|Bkj~7 zo8^OY;+rM=nJ(P5mP}G^%XBr+B82k((e!3qi91bmX$rZ{B(QsG6R+~Av6z-Jx#|bf zN;-)|Zk+SeGcJ&;Rc%U;0ytCmgDo%9l)e1Z+|;OOVE-)WFJHqf9Vqwh?xX5sr2XYc z_l_)A^XMlM)?*GaTCnaGx|j7xO@-eBVX2g(uXS*v1m27OehOV050-gXu_SFT0lUwC zwnaNOvrRdd-;(fQ4m-MJ*Dr~?=B#hk@<}F~y8+ASk@H~yik&YdXfszbEA@sDkK^3A zx_X>Kp}?VdX$aS`uncAR>IN2+BeA8UlxnJKsm(RRw|(qIveC;Hkq2h~E&}L>jvodw zDMH(S3vb)QcL>bA(*YSPZ_4%f#OEIYI~7PczJ=-etMc?o)#Fe8=1-sRL5VU`cZeGA zTXe%wl)JDL=;4PX5OETJ_k#LPo7WrRm{SXSn<+oa0vswy%u8X8qDWSt&&PO?O`K7E zkxf>p_E|q<(dECo%OuW^@-d4l$HdY#H#qBSGfjY{TGTqsV_uqvd*??RdnYThld zWo!$sm2&|(A?%20%nBxmO$Y-I&U3f_)r@#Z5nUR!DBuW&IATw6d^R3bv5pA_OPshH z>5|+=n^c>y(N?V0_LTpMyVaPr)fhm4OTLDfZe!oaAHqyL&8~2pE39*`Tp5%?m(>Z! zy#I5wDDc~|uAK zMaMEq)%BrXYjfmL-qH*vIOTjnjV^FK^eyEhEA;J5N*tgahW4F+NTBlX-dyw=wgK~7F(^($ZiUl%3Bp^GV%r^bY9 zniRqHW+?kvD6ylNCg`QlpH?`*KsZ;s+)Adg6nIWuQ|VQOvBPKHLP}WAYy-5;--@jE za~}zf*lg#ahGKF0ZvD44it%zUiy^5$>LI%h#S8oPRzaN?ugSa(OpF;~oZ{kwWY{GP zW1MMwxbY;#40VCz1IHcc zQu@pQAS*&Vo6yAV*m2?7tYRB;hDd_di68QcY8VSv5HdYiJBra-n2l1(7ahvh+KC%M z^1PPeW}~d%9I~hV*r)v1&-y}GHA!+K;Kyc0(Cr3V!lcU|`%P3E>l44Uyb`Ul_>nZG z;brCAni~$gxtvrRuGif1#_aOibO!+BT6h%G9KdB&ml4`DT2gx{DZ0~Av3#f*_th*{ zu3kA+QmkB~p^GaSQ#2LyK1-_E0yGwSK-9VrDD$69OY-2Fk^U|@sJ}x|a**a&P&aJ2 zvKlQ;x5O5(R?e4!MI)=Me}Xn5?%NSZi5)q0E3%*+0~~MR%5dJZ@hzA=p4|p_(`BLj zXUwwT<=GJZmQ+82S82IC!tiWm~G znYpy~0YpqH#_}2Rb+l>=&F1Xi{gU~O=*qMkY}s(UX+?vR^S6zwJ|!9TUepdp(9$Ur ztDrF5TEa-K0Y}@*4-lju=K-OkFKTW)}w7-0C81>LQw4)d@cxg7AZs zWW$q5i%~%NT~KEa0b2t{Cw2pTID9rNhY2U0p-%*@mH}BL?tM0EfdPZ{X55p@<4Q$e zmkJjGtzGo2XCb*XEew51(IN4@r^TA55~mN5hT1)^Y-_l3SoJ}L4CE`WXNW<2gc?p` zAf7uRUPF-10G&@4>-9Pb{vaNGD*7qsp#`4Ps?mNxfP|G{xlXN5c&G9)g;UHN7?`>2 zJT0+hDx@ay7Qck>T{enA+=AippV8kK8A~usDkz2+S8z?@GBC%J#$xJ;^=4=j%3g+n zhM^7f;50?*1S(dmD7w$c=4B+VW)rcBN8FTK4RD2@WQA!~GCL&cJ-nM41#0Ag*OogX zm2|)yEQ?q*Dy0?!dW}rQsql}*dGM%Z8L^8bDsB*4O;E9m(jtVcq9f+6;-?FGi~0!lZs8UK&X9bch`+(LKHJ3h$7Y$7;u$cN<2s)+xY#_s4kqJHq?tYs^`KL1+Jve!cwX_+ zaY&hE2f-_F|;G5QdIBh|7i2(MHth z{Jv(Cd_x!4)J(slk!AsEP>Q~qW5u`f$Auoo$R*e2&4Upi*mPH9*PxBl=7wsD#_2|U z47Ds1KyzFNO8(HDa9eOR&ixh@Kl@@tPr%<9y4hiq%Sp}Hs>dU7rjU$9wStSNuxWZO zjJqmc3|Do)v1yAX(C_jNyaadt#JypPVPMAhC*c{-`3ro)8Ntks6VT*o!+yp^(tQ_P z0G8LQv=pbQ0l4z%L!m|RR8Dmi+RX0sB#}6^IoMvZWR9Y!5NYLOCAtgINS=`sre%nu zXTlAC!NYoX#LZ!`hsGumW1*)0lr`}r=aFgTm2CX27`$ldp~ouiTY^X%oI5p*tejsh zWgEb`1zyxjIOIu+B%Cut<`*2wqf6I239$SF&)k`n&ila|Af~)-geb^=SECddYkb zG{+vTJLmXxatp=sC%g72qt3A{8esZR1;mtF2eoUl9Kv=GVkkoQpE|}Jq*MN`8h{bd z(6M?P@N|@HIJq;+abe)}l<8IAG#Y4-Any_{Njv)!EjWH?hFy*UN66DV(T%C#aK7yQ z&9?ixyON{dVP8VIosLBj(H%BzjR#V-Qzg;B(HyPq`WODsO{7d81a4!Bn8R-w{ar41 zbZK{*g)z29*+-Ari0>L$W~M8#AUq#-$iz~c!}H|R8FE#SS;9H3FWfp{7p^urmyk;{ zioT9B6LuvnzdsA6q0FGsXzZ3-FGM}3L&JE(^J89fL16{xJoB8R!#0T+w(pj#k(X96 z6C0K;+M;9ero|CY1Q7)kMu~d`!toYA)ME#IUSUIL_NHZ&34>&C=~AedILZ|7RCl1# zvH5@`__q#pc6M{O)MVQhCr6fGw>Tbap6at`1X z&RwDMF5XEhm1Cfs=r2Pe5@DOAfc^AdrS=KVXN-l(9iGQReFh!d#T&Opdz$k$x(>e$ z)uR)phE)p!AscJ){(Q(DiofO%hR+r5Ct9ea8sM?F*i|TT;t03GmUc8yh#g8(~6)nQUJ3hu70q7skdRK4a^v65y4Od`2WYsi^ z=j@;_J2gNgna@xUmmVhAQjR1Le?jg@kocfn0Z5VO*UKWaBOeT-lN(kx=c1+;)8cay%QoBF<=HY;@rfkzBuoASLDX+a#5TXv-DsHfvFt z-{&_Fk{|g??vNDcksRmw2WXGLa?|66PzRuZxC48pDYjx$sC)eFTN%*)MoG|R3p49% zo=dhS6Q^{h?h0NbWYS&{#?Ik(=2P{`-Th4Xsb%E=J}ip^#G zpJ;HQkI3$Tc6Q#!@s^3SC};A%Hxs54K8xyHhYf=Ewz<92K>Tip9eKdvDy`hsbyPZ3;Iw=3OQan=*Y-O2wc;L-v?puHBLDM+4prh9MC@Izq_U zG**jNfMLxrB(e;5j!DDdS{i)&P*Gn?nr!=85`?=}qha~*HzX~mU8!hPz52reYYZ3l zM{_1ke?x}IlgV2GMGVWpt+5APc>4q33x|)L2F2Cif78|#<^G zAOh0AP=li4*%Q3Yulb&GSjK;K_x=Lq6s8JiO>?CL%+*&J#tPwU+jUGTT5)~$!4El{ zIxPUf?A##Sc?#E3&N7IdNqCWSnJ-nzMXGHfOZVJ4MS941{kU*edD~lU(y52jZUA;0 zupyfiVr1vh3H_W;yacQ|H1J%u?*8Lr-?tDvEtYk6=n0dmZQ>;wXb0U&xv$_~Qw3o0 zw$YT?D5M_kYZ}DFXLv^+MD`x&JrE^SV!k104+%_76DEl2Kcc3Wj?|9TBIR@QG&G-tEw|+?X6(YVqQXE6eG_h z@->0Uf)?vhqmq|wGgh3yn2}=&w2$UQ`rcB zpIVfm1*wZ5Es=j9YV6q4>+9F1F73GY>#FpX7qQECa)1(CdEQMS@Gw#izh$Sl_&leb zr@NoHD88@@Z}}h?yA|zW-qdN1`Wfix)nilu)Qj|i`_w2UUPVWA{pfO6bWdJYAOb8k zdwr#WHGKSS4G1qr8KtaL#toVcjmN-uO=jB#eKRa6(l+b?Yxz(X9qJ7B9h=38O}aDF zXx?cr=Ifo_s{`~Hj}Pfy%kx)O z?DlWJq-zfYhEnL1k(gbLXQV~Fw^?lS_oU-f;4!0m?C@+(A9e#sdhYAnTgK~WyVF&U zNO_>!Cf+u0BkhN%Zdhaywxt){qk62@m+s4~#PA7yp(HR(BEax{E42}*(gy03=3o-cc*^J|dMl2wdG;0lOi2z9r+a9K?ihgOy*r1@IG5C#k{s>X- zA`4Qx?}V|=5QBqF)<{|el5k-Y+l&3NFV9mDo+Eq_S&k(>$LaZGd>KD$6-aN(MA_KT z=7vp<@?tVGhgsUtzGd~de)0iU4lL;UaHumG6~E{_te?-`%+4;((Cjt^r6C!g$PQON zwB!J}QQi5{#_kg_7I1c4#4NoaW6pusmPN;du))ddGDA@oX0JuZeeJd8`pGh<`phI3 zKb^3_NIOd2w41T4lgU2bh+^-tu%FxJIf2Ws#Do6V{^o$QGg~ z`YGRN(AuLomra5yF{Ba%dF2kmWVvIJm_*2YNe?u0a!O8!-gIAyNv-6R)>o@lTIyuZ zBQc8P@P$C7I!wE}ZE)-$G=$`E>(OC;Ad=@Hhq5{DA<%z@$q?u0BvV`F8Q>}K$TM%3#X^Zil`A;l z76R3z>%Wr%h?@JVEC1le%-hC3p$4oQk%ejc;4p3?))J9pXGP?1+foSqlw*wK`PT2F z7?gx!)v?K-V;TMhzx>X>LKR5!QS{^L6pde?_>~^vp(3y9L%8VLNU2ulS&#tHmFi*a zE#d?2U&GE61kDTrBnZg-{~zq-U&78mNA=UryiwKAMt089Ot37dps9Hpo5f(V3(#z{ zTMI2!1hs@Hi;_*&5oOKJO_a419WmV(n2IMS2K3a1uMGVib${wSqjx(0hnuhr679hO2HbS9;u_F!X5~9O*2yRPmoAECSK8Jwq@=a+ooReXTD`f z8S+fNV}FnrMrHFEeJB24FPzBgGy0DIL0?#r-C^{d{DZ&nBrCx9G4=;_VMex>F&A-H z7NiHXWo79qrqnyGS}=O8b+1*+i`>`*O_i+i;{$Rk{Xq;Zg!jyn5`e0}eO7Och@dIX zdDh+$&cSVBGJrfO^|L*%C6UD46g4gLl35&`HXm)x9!H%T6T`Fwq-A5w5wf>c zZCPv=x-^7Lb@fa9;)9}e=Fi(Lad{fgLiQfdVWQ2f4&;^F9#3n>jkz@U5VBMQN*Bgt zmDR|_`IKm8&MwzFMEW;7U!RG60Z7`NeBZY-IZa6U?%+J+Nl!GDG-i%|{>ec!E}88e zb(XTa%P0QumVK)adhL{=8OLfin&h=A890cG{k6b6qf}qT>c3s7=mAr+4+#}4(-&T` z<2vsIM*~M$*;jl z@}zj%rlf=6vbgJ4F@o)s)|ZE=h9Rrnl7&bd&ooVS(s&9J``x=G-5WHlazgC;V3L&8 z7v*}f?ATqdUB)?Y`r{CHGp+e>i>B`2zT%NnlfzO}t_MK;s5kkr=)loxwHo;2TdR44 zhRBar%hh0KoX3M-VPNgw`@|58pHtO&A7D8bra|Z}+hcZENfY3A-4Qfy!^4DhO1pUF zMs;SeKTERGH#NbYWd`{i*f_C_IyFR4k+L(gGP5$ZGPE*CWRc6%zZUz~a{F48Dk+vc z3vOkIUkghmrZV|!MOQ{sO{1Bgo1H_V7nRi$qpz85!(3sH>b%v+YQ@<`X!C9{Q7*q` zmHk3Q6<7u|V~>=5IGkNM_M_Rx*)f@`)LUekwUgeo7*gb-)v$=foi!VW|G3~#L6X9j z0uq|*H7t*|nLa+8Wn5u{Z90GscBZnqJvswu^LqX?BurP&ARg= zrB@hk=W2C4B&pyxh|a2B@>;(b^A*Wc@xB>;WggclGtw+%{tWi0!&_i05gxZermvD7R$)XL*YqeRYfY<2 zbFw3LwGP4R|NCz^1RY5R&c9y?hb|Zh2=#xf-xYCnax%3u_WZA;BUM@V3!wLvbkJ|v z>Xwjb^)ZB`wnqF!c@Q(Uk%mL~kOc4(cx2g8xHzuanzdnl#_>P@Bp<;VM7ov0zOhLi zp>SkzzUE_jnqK2^_J4nOL)@hzIAM(Lpl!^UNphE&+u**YbkgYOgMj0{z5o~j+H%_T zE+4gh3_A8A$-4XdFb^k?hs?o{HJ1ugNE~K<>K4IQ4nhV4=O4QJqQ9oCWR83xYj7Sd zoU6{h#QVHwupN_K{57&1BI$2$I$lwK^>SQ{u6u~rLKcvi4|5zSb(NlyJ_NF?N8eKx z8d~}u2FKvyv`DVQ`S8=?pva>rGuuHIM6qee35-$=^-5Ryk>W1hPT{xwwov`*$W1Bb zc$E#UVQqdgR#aUnEwxgw_EfC*RJ_6juR((nSM$e{ATu3~!scE#I2eZw`x6c+{t8(? zjcZ99&vEjvK+}*p8ayUz(w|Lc%|R4-5n%qK`1mW}ZQObO%}N{HJes&m$@=Q*QkDIS z8oIJ==Z?7k0%28$*Md7aQ`MzG057{wy+&nplR%DC;Sa&{H}5TGk%DbrzrZpVX|@$L ziTj=i>S%c?)wvGO4 zKmB`RRH`oLz9EX%Z9JNGMOk@K1_4T122&|eV1@IV$SG$bE2FXrxu3ueLu=w0fo?J` z>14@ivs%A*01}Qs^Zbn#G&)3N=G*c+C8E8_8e40j)f`t|qWN~$Q@7_+?8k|I?smr1wZgBiqS*qzvg2aIXslhsFhj8r|%p<+w+euj7 z_r312>pf1-)mks18h()cufvjy&e9@fgsho487@d}0U(sPxk*^FYkBGpr_`Sdb%;fK zUFD`SsxYf-Ld!JXnm#bJW`bbQh4FaEyH$;$tJUt>s{{$C6&)IYEqYxkzCa^E2s$Xa zrq=RgUy0DmdmlfpqLQ2C6dV?Gf;;4}J8nX#lxUZCaxU2T0Kk+pN0X({)=b9)nAC$2j1{CB92%5MKkO;KnOdU4(U%kmy&cz`(2!QXd6DUu9Y%64AC^pJjZi>aobw z0_{(d7ZFh}L;kCvNEZVVk1uQrJk@ge%X+*;ph402Z=?k07kwgp61N0}VWh-o#Q7O4 z{_h)eH%xaRcj{J$(8axQUB&~`lWGnMf<-_U*e7T1Cx%g`lH+?X z$Uc66R1UrQjzaWYNVpeZf{@l-Tq(G8VN`Ow~?=E3eT5Q5cB^mfQXvfem#;5%}xI^$*EC? zbN)(lKH23OO}gliJkf_iTa!v!Dz%WcMJ>Uy)`cx)kcCXUI^^1H+$PObsCssa{QC(D zrxlsG55AsBTz)5IrO*gO#^zpMv!nO9H+f%3%lC(;8-Gx&0R@as2ku}NkI8`z%5g@! zJ$%_QE9J1JA}4th6^v&J8?E+`C+5Xon?2a=^d%?^{vkDN zJh*!YF?IGrSz4^q+aQ2g6~@evJR0sQQ^Vm;&QPz*m(U{AYGkl74Y<*PM&|lz&r=?u zQbtq>J;l9-?m$L4S1|E8!4XZpM~&<^r&dc<*Ztvv3Jogim1^$KvB8q{E?h`Ez9`l2 zm}cEoo!>oxV;*+aEMVj0gIB0}1=Gvb_taUg$G%fsF8Kb_k-Tela0~KmKcRkIZ>M=A zn&rowtqVT=@W7T_;#%?ea0I(@@>NL9{`Pe^u)`CFXY*`#%^x`KUkevMhA}c&Mnjk| znL7?g2ZIq{WSkw4kx3cySqo580{(_v2VSD8Nax>HI3xkb^$4b>qy#bfgw3L=q|wR; zI9E%F6z4K-7OkQrz)YQD;)NXVItA{_uJcHc50oa6KF*|InrL3ROPg;$`euqgr0v6n9T84)LOJ=c6W&ggV5C{ zY?lhXwT$JgEtQ^rSQEomt6Us8^S`Y=+#8hIhAI$r*F2oRN1)NC1Ob$-UjG7pk;rq+ z-x(`xj>n#RQFAfaERXJh~XV`+=KM4*uI;u34H>hz04XMWr;;-SCKN4UYSO zZH!T`rCKrn${)vLa8&YBw;&f8Dy?}$>PGn+rWg4ayv2QAERWoBVVay$mi8>-;#0pc z?zHX16^}V)uxzrKzq3epO^yvGf<^}CmV4-elzfr-<(dtE(7c1>payoi=LswP2n6K0@OeQ5T0} zlm!Gc{*rxWU&aW-ehA_>ZCL+}SfcxXt1(YCgc$CBwE`->=)QFSv#6;0#d-YCfS9Uc z`*lG7?w6+Lz2bCKD%^ms^u3f$Qq0qy%C-=;p&14$V?<%pbJx(@ww4YilIauS<4}Pz zA!5$r{W6|;TCbWak#duag@@-KUISfk2PY@?AZ3Y8B7G@PNI*$Z!J!x^zKkQIIPc>Q zz^+kZbVi6C(is=b2g*ANr05WKNJ~nixYb2P5zE*`S*13OSc}$DHT>RBb$T(nVr8mx zr5YPHu~^~ixztY6vobf<2^M4cI9IZnUA-wA8+*I5JQJ*;tIY+SPt7>>VxG!NH*v!V z-d@m>3q`tRuJ}mBXKK#@=@$sLgI^9IF-nU7r^Y+fiH+J zyx=v4ELW$^7A;^vv%4Vg^)9exBjLLH+X>HdRc_oHyefuyIxh)%8!FIzV-vcyzkmw~s#|b`d_l9@xP@&cUKdYaU?<%;bz2LQ zc$ZEK9;1Q?^q_&DNK}WVFRIE3!vBlin=cLKEb5$xXcJh)F#l{`nR(1hj@KNh!eEMfD3uA%ARU#@qoTA}PFZ zi$yd$4nGbKJ$ok~214a2h*D2%)seYLib?LgkckWXY_YUlrAG4%-eN#AOS1HxNJ@%u zad}<6W?9R&da_05A)fy4v&fZ`<;Ax7HM|HGqs8v^SH<)VnCsiqJtL>*d9%*~Vg+o4 z8h(}~h@A1NN6R+`5=GB6J%cLvB&rb@0m+aw@%G)rHGS5CH*V1heA(i~^_}-F2s|7k z=z9D2Bj6+yC>hV2`|?VCJSV_OLDjPqMKuSeWhUy(5hT=%*Neh!ILjB+zbw)Y%%xm8rpe)9AHrx!QfLI&> z$i{~kYmpREfJY680NV+o@lGSG8$?x`ezyy5i~9!XS^IXvVM3(DfdzL4RF@h`NNDRO z3yP@>;Xx0__V-s1L}dU=>LqEArC+q^cH4_>aW%E)JDp(J(eWbS@4b|P5LM+y=_8XP zY27HydR*uS)hvQ~Icc8W-qz8A4ZV$)@vRDQVl4puiWcv9f(8pcm~1{Y1FdA_1?@1% z&Igb1W&BbOF*!5Q=;LmFHh_pSSqbI#`Vp_fzVdE_;{3#^CN!Lgtd3~1YHo!*LS zMqdHRV}^4U85i?3JDt2Wibc1dT}%dsK*D0KmB&fJ)vMKqwI})Sv`noI6yl(EMxl^P zLY!G6sUFUUuCQiGvY$i#Y}K6i9c4>1N_=;AO~Zz6HyzAymIN3mI(K;TCsnN4BbnA# z)cI1R5S0=<;-2|-p)9QIN^U$^1CKUTH}0*v-ywBlOB@vAvtt`DSTK6#>sE)g*XoAX zh{*!**wn)yCSpP|qkgDe81dC~cf)L?NLLbRQi~bQUDk>`r zTW!~mB17|(BehaV%a99sXwDV^M)ZsuXknJrt2!|{bf0gVb+NdE*1Z9*JK~1F;$voW&pfj+v{1KXD zG)}o3x2z>(F5>gb(eUW)3&L2SfVnizd-0lTXBfuIU%N0i;YY9ArJ(hj5EoDZQv1;} z{s>($C-o7xAxxExkNO}=3QG0g8?dJKi(FBAht<~g5E-rm;-Xh`&Dig|1|EHB+|A(a zm7cm<9edMGk!*<@Odya;jbN1`q}ybH?@xAxR1dLPT!M&GYA!U|zkK;PVe;mwd6hkzv&HY;_)+xpkSCA3mni-!xY!|2 zj^}nPk|>idOx8Dbvp9rHFNt;6Zg_}0uBczdD-P|ngN8z3gF1(YGX5@$>z@Q6B$%rB&~g2! z-!T&ip>x8|0qk)>aFivEd(dUML(P5Qzj8}hb5*Cyz_w+H1F<^dl&fS11SGp$F{={B zBsE;Qb(dWF+>~v?SP=Gom47=Lro-tnr@Ppg@5~pCYkU2PqWfUHPI>GqTzj0feS0tY zh>@YpyWHP{$9y>z7i}z}n5w!jnL2HYF9^A3jG8}RNTN$%ht+MmGWS%<$vkMUqynh2 zM`g$N;bV!sIMiFD`8Z*uB0z;7RlB?%qq^-XJv)N3aZ2@e@QXt{aZcry-FXC2`qAf( z;86d_T^=uNGrzR@_E6|wI25}5?l0~3r&Qw>#L(oy!3ozqzhtX)iY#XEELQC$mKl+W zH;^kAHDiMdQh)B3(r<-Y&wfhkk^0*;)??*$8-twIHz_MHOqeBbjQz71lQ5Q9Vx!kq1*fAn{q;RI1VxU zX(ISS_CkUU5}|>cho{T}$y9#HhuW%S_9`5obQrtt*yt?@=a=%D^ZZrpwH3UdRxN{w zs9sQ895mMW))U>s@kE>#(8p=sOU9H`PZ)TE%}(}vOotE?>7`j?>u({P51+UtCompM zXoOMk8kfGzx&B1ZH?yCA6TS9%R4e@lVBa$lV|pb6dQ2=bMYsPl(!wLx<8jkJ?%8!x zXkNT?pb;M{g*$tVVf&7*pV~KF(5KJh^RrZ1{LM-X(cyuNPh#SIrwPA0uAgdJ7kuHQ zUV)rQ-Ez^#q?|c=gC!GlE!y^}n%%YOl(tZ*_^Y9_9Yxad;a_~}FG2h%RN}!Qhm%GH z-tt@_x?6(r#N?Cn6YgxaBV1gzWUW12JZdFYp#)gdn11%fzI1Y?o&uDk<~J8}0;#Zv zW8WNlugc|)v$>DKqj)3)#Z=ki&Y41{3&~%sq(*2~z|-8Km}q&zbDA0x9e)d-8IvQw zk_&&}hJR|Qhj{?Ed5hikMf@0VYCVRsjbbVZcF+0ZwZacX1&F)f9RXO zYQ<##Z9*e%V`%RD&-V3Kr(uH;jZa<#tkfswrXMy%u0jko&A{7eT_kZfgW5xKFSMMM zEthymZC}2x4pc8;b_i)TKFcjx3mvwCNTz3H<>Wcf`0b`QTmnS@wh{za=ErkDQm`o$ z4Wc^s-Hr+6gL{}xsn>6Vo2oQ}jEYG`JQs#65-X3X0BRN2Bk%qO%yARjsMb$1<1nW! z4NTsoTzR7Qx}xopI&P9<@4%Hf_lkIRfvrKXuuSO|zvGWbkKIsPzg1q;o-$vF>h)9% zmn_}NyhW_A=2v3+CJzk>W*bz$#a&(OJQh`&8PcJk639EPW)H&lWI%JX5x^gpzd@26 zOI=bd&5>GcHp(*?1e~_L3iriGfgDps($=25GkR>$QIXyVf$*$Aqc+Nr*>z)yd6%tH zw{UzLq`^+WwnRD|a;(Iha~|M{b7PG zqxH778vxcegbn2O1plg!3R4@Aofg^hL`~bBX;_yn=ISyQhFt~H6$nswD>9J+3VZd~ zw=N#BL9K--bgkDrHr?u<)@f8Lc}llu_K+18OIN?QPCAv`e`}@oeJi(F2R-|xw=oVd z>(*mp_L{OnlrOeh&1^JFXPMM8tyWw%D=#}kqvOo_v{9?>`X&i|hJ0G9J(BjaNhvoo z4Z|yy1Ad0z#)7mZ#qL>#7c?AZ%y>WE6owp;qAh6R)}}X)$BZUxb4=RSGlloU$@FH5 zNXvRLK}-i){%E+EMDZ?3;+gbEJ4J7x9Hrdg)HWdCXJQuX!C{sT1d5bqjy_H5;Q$>+ z#kd?h3`cFAE(?hZTP$e&j%yo&o6+$58l@?0%^41Gx}sIV>A^0U06`%Yu0>adBTd#5 z!V7Vhob=1WyDuR?8KBoLoE>DZYO}A6eq*e-s}tTu!sue)+pO*S8^5@PYA+9(R6#c> z3a!yevKnhJCra~nT8BUP7c^Ns@%rT={fA<8DF=sto^5I3V|1S?{FG-evaBb`#{*+$*I|~q{A>_lo zdtTllLezqJoZ{|u9=>bN5PqHAX%J#>&K>8`H9^oS@Xm~i?Tn+$sQ z!4WucKH!3$@wxQc2#IHb&jNjLbyg=er$-pC`*nf47<`;d!74mNaS7*h?4m896-J=g zn2sna1V+vX;AHzk-MY2FBDi99Bo9W=h4ynU22bjdiXv5d^3)4YN6JE`SMqg~C{IbD zG|q#x(_}(Oq^8pe1o(-N$L}+v5`W=q%03Q0pHFH2#1R%eH6RQA{eBkN*!&ISM{x}M zM>i#L75|xdWD*wk%;*c7&P~beEx{||J(ozt+7GnOz-)T|6?ukdgn=zyrCXb5!~D_u z5bs!LP<%%Frq&lk_{lXoryW_~;~v^V<%-8l_@ZGy#_B}J59OTEa{5j4+L?iWgU@PN zl=Z`WMWUQ9@h9j1JCI3!MKjWWy!?B!vqpW(9aRkNuUwK@7hx!@7Mf}g>|t?ZP=v5m zL#1j^ix?^#K#5{}-A2yM+pW#xyx9KBgd_SB(<_dm2#Fx?rI>d+6Mw!0hD)0b$=UpR z`{m<$Gd`2|q4bG-#pL{$PwX=KWO3-dp zlag6+6b2t|2dr0vYsYN$JcNQ*AHL5qsGJ&{ExgfC$MG9Q+`PJKHRgCHA}HFjrD)b} zUcz`YhZ2&8X9-R*skNy4fcy2LRnsh3P&zyIcLQB7 zkMs?ZTz|DY+;q)Wk_oFHFz`Wt&gJ2S#*Y&H!4V?wmEN{xpIfHu#z$~D(ps8I_nEL^ zdu_Xp&fvr@mAcq+*;<6VeM`$O{iP2g2`m0;aA5q+-eG248|&58)h_ix2#)2J=s~iq z={aI00hM}tpbK+`0ZU998g(KSFB;!eE$(|@FV*%YZ(w#Dq9C|?jI)U*hVB;t1$dc> z`(>V!{p{Rcfv+ClXJ$uLn3FE@R!N+3;Lqe6%z;*Mx?NvQs(36bQbGdpJ|L?9k$nC+ z!}n<8b!Hosg&pqT-{Z!ow2nE_Ke6$pu4bwFl%I7-({+?N2R$mfT^?}eG}=Rxx318t z*h7V5I6#NHXs_PO3w?WD9Dw9+x&_I%ejXS|--S0vZMU2Y{!4~)^B6Roqtehh^<7+Z(`!gNm*kk@O%ShckAo_kxZjn#$2^@ux0FV< ziYkNUt`KYPVy*0c(MZ%3It>OWJWG=?K7M4AG+mG#!%?~-+Lgy8$MDEHGy{%0UIL`7 z!H{B3LJi&N_bZjcnOVq4ow&ILja9b^!2TtA_Z)Bxo?uvnB6&}Jrpzg2O^uqxk|;M1 zodp$=P0saYaoH*9ns`leKgr*DL$+19syG+9Mms%zqrw>v2i|@%pn4fpG@Te%C8@Ms ztQK`>0_2e86?PNYKuWSDZ#`>}D~jNH_4C=?h}>>l@q+4>WT{deZWUJsT!ilbu=s)a zWK5X5UA*83la8+IL+ZOLX`c|+DU#SuD(3LJ!w56kUr@o2!89!7GxBi8*OAp*wTwG6 zLw8u4I<7&)>?Y>84|^w1kMz~LNtB~}>76w^Wf+Y!PT9z6!R>AM-h3i|O>cRR8f z=JIFzgUGo^f)~;qyfmznR7WLx)ZxJ*r=Tsg;>EZ142=NOBjZ*7Ex`(!g4fV$jDM7QN2M*nZkC#eZ5&u-!7M2 zZlUw)8LDkTxXi`j)!P5cKN-mSaeYlf7vzQ&drgq*J>%Zvtyk^;adMLlGQF#SoYN-_ zzSWL=tQ=7Q{R0%W^t&F~xf3`#fLT6FF%_r`&G92*KaEj4cGvV5$$=WSeq;dx4e=(% z%*t1{3|b#y&szB13%sVC>>w5zaSs>SM`hPnhV!L0;3dxCUbn$VVI&(F&-K|yAc%06 zj`%}yB;Mp5FtWkyM`E~BqNSNfQ!QRvpk<~Rl*9&K!>go7gI+_@-}~DaMs8(<3|zuR zq)nWvq&C*vo8H-dKxdJ(S@tZ9U6+pD;)u(&P*Bch;&)}}q?IOSuWsp%)-sHz4YfH2 zi)ptiwMAx*rW=NJONkoufVQ|IPTF?>pv49j{lipCMiT~jRnO{JsBi`0Y+~2inSjcH zOF-r~#%x~GXm?2FQsPynzL>r!E5vq(EkPp>t#T68ql)wq?mVe=JyL>?vW6IhpB`j( zNLQ6*PRHhckfi0L*#ej}y*F!BoV~L${3$B|RCW7bl)YngX5F?eoT``=8x`w`ZQHhO z+qP}nc2cozTNT@>FYn&_p6~4Uws!75ZMA1T|K^`D*BE{FIY#d#gb1V8ll5i?uvPL1 zz3V{|h52Z1ZDviPJ0t$t)0oN0%c*t18V3>OO_>-q7c(O{_7LVY%8TFQI23SCj!~5x zGnqCVl3Ezhl$+n2SO$|O^~I6lQy~XGY*DWqHJMLhfES6Z0m&nnPcthldA7{dBrI$!p#s_>+?>+E`8^< z6{eP<-#ZNH7&MTCTwpvRNzWr9`YcZZMk>{)jvGsy`dpDcGi@c^WczRH3ii$7(4Oa;%P|0c%zX}7W7PZ(5|VSL+M^dM z;Yc`=m+yUhu2SXJHCmY`PFtW98)r-?%+{nI=cET1E7_tf6JeJpWR+niYgY~n_BsK^T1$3*JQw&MU$Y69(Y;s(aGCg=VZxrKTp!?` z@XS8z?|>X+vY*o}MrO8+xT=`y0Mdnx-xp%hnfa^2)Lg7Qm+O9OmYbgjO{lh2Rx1mN z+*F>dYxXiW4*6+f39qM*F>nb02;P#2^Sm++134_zF%>ge8Pgsj7jo4pR-@K?GGcHj zT81F9bl?8uSVe=Od7!59F_Ofvk&vI1HLwkmI$-dTHdqMmONN>rlx@zoVeZ*fL zU$w#nzu^>i5rNsT;pMC+9U!5b(HsD8e7a+s>0n#SdIp+2y;QZux#c>)lI{#Ky~5xZdg4W>X3;m{c}k0Tm&;@R%B8vLvHOxF5-ZfDjwLH z$V+k^oj51t%6Hsl zKv7G)Y#CZJP*=ozu_qs-?N>iZYCU-PTeQq$Hf5fw_pd+H*Rp~~>0hP^q9vMJS`Bm} zH2h!9@|QnIILROQ!WBj_WEl8%oIuWhxzJ{eN>p|pIJVbpFSoQs6F!K$U{7D41CX9N zN%e4;hH;)biKFEo4`C>)!bl07C)vLAYMmDlNv5W6-!nIHrWM*FX<93{h{SnUAe86* z7ukH;|K#$__F&bxWp|BTckAA<@2f7k4r*!hx9cx^`8F629ibeG(B6BX4_UzMucJ@h zjjNO;u#$_O#gcVwP3G}#8=LHC39{HGN?kwqU*_qW)Xx9mes$*vC|SQAz2JUoVi*l-#tXf9ZqtqC>oy(ePMEROP%IZ7zi@EV|p5Mghtd%4AM~)eZzN zPs=@!#9KyGMhp)a@2*j>xLji*C6sLD&=F1JGHmFQmg|9H`DBzC#inbliCc|#DoES@ zt+4BiI$tYag1IIpRAl+o{U9?=9zXKXZc*D|(OP8qtlZ1Pf{by;2Y>lkXM+Iy`c<+s zz_c%JnzS8Nq~i|)yUBEFb%3|dQwXc`jQ1gHAlzzMtB^?rtFOvRSk0}IU53LslT4Yr z$UTb75iIR!z9Nz(l8GRmo`zOU((fs~3y}mwD;xt0nznbEb~@;iK|!_tn<18zJq(py zoPCOO|F@0T>4wJvg<}rkfpi~q)s(K!YoEXM`1;2B;ah!?Zku171l0f8VTF#K_5bww zM#-;#4Hv?5tr!1exX_z2TxbqzDEx;%fvA~WX*Zdd%)C`YJPENF^k8GC5PO9Qx;33BQ%gUFz0~e?hhEQQ7kGh{Lg9>~RKGPwHpG*i zEEHgup_C=MzboD9nY+a5P$z8$ILmvP|ni;)$@x*#hQ@dHP z{0tHp+aR`j^G4+nnn24Dd_0DegZ>7^LzHtjetQaOX?;3=lv+XUK6+(ZytoA8K*BrV zf4|X|X28Db{|emp7hB5mp9k*mhs>mS8;b>A_@SJ(1H^=(N6x0t<+bcNi^UZMzD86_ zK2Fxx;v#vdKJ9i_%F`oJd-0wGn)@hF=no)oGCO9p>rNH3p9~qRY1Ifv z!MU+Fob851U|qZx?4}3(BZT}LsvE~xAeQVsVsveYL*i+d71XU`qF?DZQ9e=$C$$m7 zTxAN!JX82M@Jb_hu8R3h>P8Y0;T@ZjPn7}nlDAt8+KJdfWteaV7{X%g%r7^x#=E?R z0oPm^O;h7bJVO?Jk;yt8?BhYvt&;_Z0h7)`aA*oSvK%W!Uv@v5-m)Ptxv|T{jTQ0e z`xm7$>IVghq^V4GVo7)vyy|~cs#KC{dpAF_3=@TKzr2>Q6FFqKBWMVGBcKCA7IjHH z$a#TNAS{kQQK;1er(TK>e;*aT@KY&~4S99P!A%$hL~=Ic`UIVad3haz+y|gBJzHiG ztn|XH>t_D)j^@J1GrGZ2&HUk7QhHI7{p*z*)Kw1XXjqK+S7myu=6#oc1@Uh?wva_r z&kX<0^wd5~0ZbdW@R#~~a+3_Osj=TOEAxbs=C)%908Pqz>mB1=8@*(&1QjQ58v4au z;0|k#zkkpS?-wb3UwZ=Ui+uq6$NS=+Cxjwpt1sj4zvfN>85;ybja4?HLQ=l<1Wo1% z!k~G&gr$6d!EVdG?-nUq#xAFcpXK2Ub7c%!-j5<|TqX_?bgKhjegbdxPn^?S$6qqr z8Ot`GpWwezYUx>{F>u%~jb}pCtdCk>k~7?Jpj(Fvt{4;BdZs7ygNtB@a7|rD?nKxr zRHxua4UE-iuLXZLoM%|?q~;w%kAN;Wy<-f+e5Zt;5oj`o{BrExYTjMv;D|O_;OyB7 z^x#m|wM^?xrjwaGSi~Z~BTePgp){j*-p>13RDwIXdQ{B)gD1#f;gS*rUO@l^uLS>=fzj-`oN zsv~5pYiut6moBxAxACVjX7s5wro^I&G8K^l)qU~V(Wz$kx6M2jn~yC^9Z0YBO`^BT z`kIx?n(r^lE#D(HT+Vqao%UyHf9aL*%k0S0d%$JzBcT(}tc`R^f*Gc+UUyx97t3&d zPn!B%sXo10w1Tecv;w_YmAkJ>bv`EoyrGb*O*BEdC2j^l^qnF&;Ii8kNZV#20odv` z%taObR+TRj=N=@jJ>aEYsF^{goQe@osFtvusM_r_aoh*D94Bp;O9XVp5e4YXa*3tm z!&}alE7>w^5)~J{J*h>?gBhoR6pwT16l{ z?4iPjE$qTf!O#*N7&`twX!uD&BU{3OjM+Xd?&jBURVGS_Cm*;L0dJO^8|$b~t4}FN zI&l3~{vFb#H~}>H)QVfW#yi}--I#HXji+pyU-mM)_z`B(x*)>RcWbup^AkAq7~u%e zly>5QiplkPZ0cBV9fF?;o=O^Pb+7D?7zVMyp|g;zG4a`Ji?TSfZ1g-18q9;Khp zf|Ig$b87q^ruuGluy?aL`K(a)%qfiW87(hh^1dQ*&p1veSbGO+e-dJUg5K{+G>n!i z>xeXqEqWzj;cQgco7AX3TehPmw_-t&Xvvkh<&(#vaDYixpIUg5rXT)!Iw)_bPd2oj z*BV?y5PsH*AQKmrN4u4`lc`%*`jaA@d@gbMUM04o0Q|W$ZATi|FZz4GGMehAZ+Z2P=vIA>UZ@dU2*?}Py*hcv^$H+-d|G=RIKR|G)Rkr@C<^qHusQX*bTs2YSC z!;W7wWAu$K;0hS7SD(Q23-!M!G8X8^yZdShtZp zS%&bDt0rGsW^6b)xwmL8oD(k6nKS+6-fRYSRao3%p46fAKpr-@7<9Ugjs*jp{8_Er zhTFoJpC*NSprExUOH0WR2zLupcN`Y*9z~l!g?#5yZ(=il7|@uwMYPQp^QY4v1?-z#c!4W@2=jQJEiP*x)=%rh z&pAGS-l2bqK*+n|jk7y)isb=Qc2?fj4~?s^cMJO!=_77mcTbJa6Lm}R=@N!rJ$IJv zd%VXI#NuI`l5&4e#E;IQN)RVEtJTM^%*Il<7w@M`{(4{xB_6KpT&+KSORnMjvA`nH ze_%h##mM<~Qfi4oyj(%mdlPqv_*#7@d37JO)OoSen;0x;>_E~{jn92% ztpJiW-fU2%2-gCrF||%QE%sQYN;`C#Z+NMs-v9E6t1}@OlBgzWjs`BKY-SUv0l(bu z`yC#fE$QsG{l3UJR@`7wX?>wlOw3sBz%E`nkErJcaCl?F_JGf)ScOt|e!L^*R^?g`|l8PG0QH`D8nJ?|IZdvw^ox z*R`K+U5)U>&#w`K>{&1=bRr0NBTkzz!3^u1IO}HIy@ePJnVK$z**g3l0S9=TN@@*m z6TU>AZ^CV*MR3Z>mqXh&hbzjX(xIqmHXXHfIsx@qrV9uc5z~o66yP?`RnQ~?ZP`nz zbj#onFQqAvEcs=14z=-1%CBPu2|b94HrUG#5}Qa4l{Jv?8nV^BfQvkKIPMptcV2fC zYw^%30!7`8L<|$Nrf45pYY>|s#zg%B>CE)7ck&#dNDWih49E-9TEsOpJVx9+?Cy?s z4rnZB3cbKg1$9brb=Dq&t36RjRi{$$j^*{aeajF=uBD>W^a~riHGTRBFANfiP7y?= z8AAx4yqg-wd9P3W+_Pq!&n;g#jRA|z%}S3Y%BoPg{4kfP@Z!C^$lV*nQ3pR|j6xkS zwZXz|TXXn+fiX%4Gn*d&^j%D|H-zY6={}YZHFl0x7$WG1k&Gcm- zrb=ncMT|&pUQQG<3WjilTia$E%bX|p#`aCH>*GQ84N{WgZ5joOeLbd=*MbY@!!Vg! zB*a@dMB3-|Qi2_K#{iUtVw$%z+^~x>;8-(^5;<$=K)}dDCumL^y6D2@{lFa^v_SBl^S>h#*VHjzHM|B03mHmu*=x&8|+>4{+dpkl!&EMNbJcj)s) z?(*JN*KGY4T52uUWBD6eTKxaf(lGbG(9*=ssoH7if>AqX=oo{g#i5vs+~tO!$!$AC zMFrh-ZvY*msKX?k)iRp&Q!se)dU9R0K5zzwyl6#i-C(X%MWmifU?MuA#a2di?0~w@ zt$D(y{=&`G?fp-&s*M4BrVv4|zT21U>PGRI#JFz)%)fI4k>x1fY;==ch_neJ`I)8A zcOV%I7fq{TbD&pa1-Ol8Mng=>#wb_rQV$d}GY32aDRlih1BC#3%mk#95F$r^3mo?0 z6GqV&6_Wj*Qz3r^?yo!duYV~$+kcjdtavGzbzb=3?MYHQt@vvMQ)mcy{%=Hpv0*>K z({D`_^1cH3*zTo`bd>dRbp=gP1Jl1D!+?2w@q$vdGWge^clswT&nNDts*gW+AK`xC zCIb#=OC~)Law4AlWKG3&gsH&JNPmFqJpGV<4(;WB^va9o#0@4eWG!vk+?kWJXS@yE z2cw{yeGm)mDk>RC1+TU)4FkHNBqDIdz9}- z)U@dmN_U`j2?rsMMXI1AZqtpke*V~s79kw*Tom1T?S@Rr@8vP#x^MTVkL~P75EhfV7+G}Tv11ZE=C%0bP(*Q+G(4rsd+h7Cb4ERl0;_|%+(}1- z2pA5V?jHgVJ*XH*XEc~sAQXtlG7Yt#?2wf|C4kF&U`|@}{XN5+dqzw~(3o4Se|^qS zKu1&><&P(}`TuAvCswPynU#e~EkuFcT~Rx{QVW_Y7q%KZkxE!}-yUVSeVN2E{7lj) zLS2r`%pxkXKdciSR3yH}n84H#n3XjJyAH!7f`3Qa~c%g?DnOqt3yYw+i1fj1nKjlYL%Z=X$1dVHEo3q23X+QH^Qw?iYLe~|Gf zBV03N@6O6d%kLQ&2{$hO7V0p%-s;!fAdF+q-p(kg3QryIxtAXEhU!47OWaH2ea^U= zM6Tn~HMeUyPecUIO#F>1@P<`N1a(#sSI6Hvy9EL(tX+!y^Vy6#rAe5Bt%EFc0bZK1 zNyE%LHK|;6Hq}|a-8cDuu~jNy3KMlvB#`H5D+ws-C_TRYFTB@CQ7&hsw%t=e^@z2s zV&y>2i$gE1evQHIknM=1R7@=wDeQCVvG;ZO8<@fj|>tI`JuP&_(gpwB5`0M8C<(xry4Y10Uy3iT}Jo=B&(_u*- zy;t)2=~VBjd+1^vdalWP%3>XckKof5$sU7Ou6exF&yjnW`JB|xiTjkFpA_)cGH1yN zb6Ol!xl9_#aa*Z#IK#I7&sa`2i&+O_Oet2&;H4eI&2Q+g7Jpz`R57BBTCt^ zr%G<+RBXpwY7i~xcDKH7AkoJ=nTb zF4i@jxnyRzjK|!0ZbK%U{LoVE2h~iw+|_U_0Y=xBY;g?h2%K?2md5$!&Dm}es6!G4 ztAWxpvIi!O5Gw}b+N6ACh9#5J59E-UVDJ9$`5uXy_0y)^+t8h%LTQeqc*B9$XD!`? zG+Jy-mHOFc?0$Q&tjOulLgXN0ax!vt<><*9#pJK^^T3kyaCbDX< zt&hzo(aL@iPq3#UYzvIwRyz?xxbn~laE-k3;52ERYkQW?OE5&fM8)#rBmWa z=DUBVQ?r8=&zozcvGi^=ZqlGNG`sJqlVD~uZU^>zBokulW&73l?czj8ZIWTKk4Dr~U~WUgDGLqe_6I+TzZ zyUd$`DU8x~7zwpmROp)hvN;?S_q&8H4xh6putLNvJ~aMWKvnD6J}(=6j}=`&8aZo` zd)YT1T^+$NMDIb?q&bypEZx=TdSnk_e*jl2wrLNcbE1VYOsSvA-r2ZSMe?lqoRv*|fKFDc7o zW39>`K{oKaRY8@HwF0Ng=FgejmT}5E3xt#}_qxqgmO0HWl;fab;06w-BY0_0 z5T(b~uyynkl#d6|%AJvKZn2L=tq0%B6zfvGW0>Y`wxC{D#aIBdoYmMw0-E}Tg&Fc= zaKtW@Z6c%6#2twn6^1SGZ;2Z<2j7T)P?S-w78pv7w#Em?cZriEN{X{V`;YD6o4=iu zed9)sg;{$29gKfT2;dE01A+xIF34HCoq$)h&y!@1iwy=#%p)`$5veb)xBS>lRncIJ z^mn(u6x<==Uxv23eJP<_?Uq@i5y`UzMjl&Dl~9a+DNVei8dJs0sDWDkN%c_{&w%y| zpSn=a0qV3Vg70uZ{P&)o5Uyua|1}S-HCxkMXEH{?1oZ1q)_9E`+fHwyl27>Pqop5_ z%Q{&Kf6%py?^#MWA?mm$>0@rXi*jAFA1DzC)T11KQn`TknTQZt&c>u6$2bl#xe;#ycoRBR-;s+ z(yZmJlVn4~WhC`&C6asN0Rcf|WF#K=ue=@Fs~QEGR8xXl9x%lFDjihg>U7!x%VVLN zzRQQqbc7*c7sqL>2sJ4r)_qv^8Dx`s`4^l>HUpFNNB2?1l9ej!I*J-9&88qm`z}3M z^foF>muOKJ-f@jXdTw{A0%{?4#us1c?rJjo4sO3{E(6}Dp5jA`G5xMKG10`Prexn$ z?t}IylYv3N*=0WYoDlrUq{y0lE4W2sSiDH@HHn{a%g;qT<-|i%s(0Eu-YLoDr=nWw zUVyFAMF3e&PkCLv?GA`BAT`V+8a#$6TX5FDer`VsdMYa+!VD)@B9;f-Wd4vPhPs>B zadmN~YJny}D;+mN4#zsBB{Vq56-~~s(`8HQAc3?3{qx%W25>9}H3omsxz}K(8T?3Rjyz z?~L3nk&Wn${Er_!JC4LDKM(&!lcNpp@S!7>RW7tK)+VrAJ8V070PL7v#M})8@qtrf zG>bg{miWa*qSjT>Mtct29WBm<$SDk$wAn2Yjt$;}?eo>(TOnsy#i8D{oE;hd8Gd8z zhIBna0_LB;-AwN*!+n_p00Hq}{J&(w{?VW)W^HKX`cLfDr3&eaw2bh%ysSQ_k8BVL zOdir^Ij&3FEZ{ezAFXeG?&}L8%D*(XrX5S%p#F`d5MRtJqp>llkScIXDq{=Z+(J^6 ztZR<>zWb`<)NA|0{i8vBv|i4#ZBpgAd$q;pc=Da$D#uO6`&K7L8)PQ1$E^-ogsTomybvr_3cai=M zv(9NOWZv~x2!m@?=(3w!@Uq7Z7{c(4u$)^$C`*KEL@2mWr_%i;%D&Cr4t}TBd6&Qd zhtZ`LZn%rb4Q{8(K!5#SWw=PE=$@DM!p;Z%-8X~)f+;sv7NUYX3S1>SKE6>32J^KF z6y&9aOIg`QW>jWmNo$q@VUhfr@!IB7ErhAWmSKK(!w~DV+e>NG)h=VrUjIkg%9>vK zw>Lsz0W#yFK&}~^0W9|iR~rEhMoVnOD_4c~ktdzO6KqHLVnO}muXeSaV6Vu}jWGob9ux-}J z6XW18DktPvg?T+*HQu~7qASLQd7F{z@9J#zKigKQ#wg_B^+cD70kvu*jC4;q1f*V-UY`bWNP%6R{y+4mUcC(#0W=) z`ZN5=ff{GbG>Ss{f+|>c>jy*Wb!6lC*5@*|Xpx*5SYC0;!kmVKa1^Z9JR+|;U~;G& z=uDMPX7sV>%|#;n?xOkeQe`!(o9uB6m6V8Qd(F-_@J2a}qUrX>t}D8OuLp*kw{(e%r++8tEYmu-!8O%?>)F;7SXlPHqO8o=uDdL&J|?Ri1#&y1CIn2d4u!v zkksJF-6U2fWdz#@$~ek_oY-I(&{UZrkcVp=wCzf~)7pE+Kfq}jh~=M_w}C?v+BASH zD0$IGhi|0gFW&wlK)5wNZn^ABg;P>mtW2Gy76=J9U{xR!4H%yT=db(xW=3;SfYDS> zHLRHN?milFLnT!hjAJ3?N0xllK^WDyyNPK>&4S34Z7zIg;jD97`#6TRy0DwpR3|!M z%iak>;erFIP~EB(wjYnInTv3bsF&YsFDt-zYWEUxwXH?DYE_Ku+PjCx3-oS^O1qSV)YUjaCo zBUw^dx8j80jwPFm0c=38{76rk>_KPo*Q6G34ph#d({V0mAK$lha*52*iW&a0B4k^t zDdqG<3FP<{@5+oyElRx8@zS^r#xvHth=fd=3wR+DJcjb9K>+ibJxE? zx+h6l7y@cGz^2l$)tL;iN#$9Abnkrf3bUM-fu_ zS~&kU&xZ$P$3eZTV_Ha!+t0jjmrO5GM@`!7^Dj*a^yQoG3{3<`1tdkB^36FYurR*E! z%jekl^YMd{)yWu|Fq7Hd3H%Antjx>GgJ(?x+^xsP@_w>YvYvy##9-3q#x^ z5;`0BJMg+(F56k2H$F*d%VgALZJp_5+uRwRbt^MJ1S%>aU*L`4fQ@^B^HSi-sQywT z3o#^JOqM?TwbTRZ%N??Q&Xr7sU=59`M&=(DC%zFj&{pH=7-9e-9O_)-W67RB&G-x1 z{V1K%D4%ke-3f441hoZfyVE~A1*D%Lze}doICo#WilwF<|V4|v4GE@lwrLkSwzQOx6S*B9GSk#fMH@85ai_YE z&po&=+m59_pO0Uzfa;&SaR`+2RR^gcQ;0UA_W+8_TVeXJISuYAeQ0ux`x4APC_%wa z+DV2)1%X(VC-lMSEJm3I8}V`a8_9GNrX!*ZTM2Z1&rOkX!V1E{bpV6N+4wl4$`N#v zO7Ul5f2!R1I;M)^BHiN|D zb1XOo76572o^|1C|CvX$HquNpvy8ZzMuS+`@s$~e`r1Nem1A!mtVM*gc!~1yEu{+d z_n~FD6-suMtb{BXq95q|6Kz@-V_3=EiZnH6&T<+oqXcbrHkMGW+0Q-?qX9+{$CSjA znv0eJ3D0SQ5|j)x7^Oz}4OTN@ebR^R-ITc;ah8i6BaM0(Q<1&~RN)$`vw@6!d{(=W`-zH)Hez-; zI79WmAFsZf!HB^O(GKikM<7S&p_-u*0)*8JRU_+0>d}XDeFbV-lz&}!IECS5s@2_p z7&sVwWNX`(hV1v6<*{g2NHwKjERX-}`Q*iES1Pxh>BdA+pjN58e?I|%Ewm_};0kMc zNhVyMHzXb|#XW!8s?$^ec z;fZ)+KhW*(r^cw^4P(p>73>g5#YZrb`pyjli?>VqC@{22E>6TV^N#eG0{7LJdIZe~ z%z;eAMYdx9shT7_zM7WjT*gEL&%u9(+7nJKmv^xEJjkK6+7?)lElO$qWL=-T3f zf?!UrfIE3bo+8{>bUW~ROJKpuB^JzgGP#1izhvqBSXaQP!uZ{aXUCLz=7yI;m70~AK+!bXUua(e| zjmNuP${*gi@9zY6LNPqMw;$nnK1nZZM|ZeBbB8>NYh2!GFBuaw9`C;6K81q7B^l6} zmx<#!%Iuun%a&95!#Q&LJ+slWz~X!;SfOYOw!oX9Omn<4d`XzB%Cd)GuTbUu#rq(J z9DKY(2_P4+Fz_=8+(I+6ztZ{)AY#(5+`nfLam>gV&Min zMaYlW9wdg1a+xdADr3_&iMNaPY^G@$JN`6Xqu4XbcdEQ;w82;fFzrB*I8k7R zE2JRkwFNCg!ifD6bGN8PGoh`7bSgMnG&xgdX4=LrkipgIT5bE_U#7SBib|Q-uBY@n z)0Up0brCyEO=+*%|BNl=_nCyW?V$SJ>u-t|ezAVf;#%{~+Ip06N|Q-i+b(-++lcW8 zWY6_-fV$s!#ef7cCd$Rj6a9T;wD6*MASE>pW0DIOOXghd2b)KF4vywR?&^J35eM@r zK~*j8^>>U1(Sr+d?Co^DVPS=MXl*a9o+1UQLv7acdd!)+xni9kmL^k&cjLvD{hfrs zXwO|a4ADoQS3HP z=+0|V1FG1aMU8N6tP@tll`0Oim&d2A1NL5XmbEwNHhntEw58L0{9YOECdu`Aj7}}4 z=3LwCGYh%yO-@pFG~rb<<_YgB*kEAQ?xn8|pnwOE=tK;n2eD(=5bg{oMpH}lv!l}@ z(qi05jua;v=t|P=^Pov9?6!gI(Vp;6iPo+uv~Fbp%_nvoIxU~tt@utl^f z4`{UQi9ghhfXe)di_YGD%zd9H0zcUGW5yZpw8IoHKk?#8cSGp+@#m-METL>@K z$PaYci2Hd5ab%jl0?O8KWkC5z%c;yW4l(zTEk#Y0{FH;}%~^JUxC& z(z$XyDfzhgBSjk(F);C4;`wq>&4Dwq3q)J)fi$tpXkw0vzp4Q?;N<1dU7In;l17}HBJ$DqPH66ZTOr>;?xM783kAAee8K6OA>eaJ!QRw zyEtCLt;ubp@CkiH7{sPA9Y)?VpqSu3O^B<{xq*z}oG~I^vjg&AUE=34H@`+8Fv#x) zfxt%yU=YGS1b&e~K7NzHg1~Bs;R%kJFL|2*HpdFMQ~&6c6a8p8gTq;AE3+L;_S$gi zjr@{rzCDlhH(;$-f%`qk=3SQd`|UblpBa?qffNteWt8o|8|s8SwI76jrNzvzALIWb zJ^ptPN*uuf*GCI4XcB;QXT}P~Xx9%(X3CdeXkQt`3bkSnL!eTy1B4BQkU*YoT&kQSJjig;Tdvw<*R?zM(^B;xWT*rnO1Zx8<2GRLR@FI^VXMXA?)yPlppGPLVh zda=DC=}%4wlX{@htzv}@T2l=sbKOsP`oh?sl0W4IxM>A${zlTyvOS^y)m_Z6jP~hYN&XKkq$E8|D1v6JzHDr)s(zEX1|Mi0N`!vY8kpq;Z6q!8XkkJa z)#gR_71kz;11~^jf{e_S7Y6^pw>gJbe4E?Lj;E)N^$rG~kGr!gAnU;& zQ0aN#_y(D1guV_?B(!BSLy30Ud=Nj#P5Hx#Pl4KBSdob8P>Af5hx)&*Kq=#s_RGZ% zgEqSf4i$8!>932dJk|l>rrdyJ@R0A5gHp`^uS`vs0I%ThV}M$LebRR-lj(`6F*;a*lF^w$66QdH>XV&N48q84i2V`VYWT%Qm3#y zibI^ZtuxcVCI&tlE&OO#HbrcDsW5m?}(5$jxl1a_p;{oCplmip#rO z1EtEIqer^Qx3y6L6}vNGnm5kIsw7rCt|y=WGG$&kYxMT}Z2h%@b2C#h5Yir4aQXvh zvEJJAn{c<$)0Y%ii)J=y(}v+YEmdKMW_8Vc#Xw%T7_ns(09ja?;S*scNM(rlZN%)s<)Xmtu1P>r)FzP!{ngLDJ!pEx>&7J(jxfNcE|6=9V2S!w=Q zn1*z#%tGDu6iW5FTCIQsurM-?`=}AF_HVfl6Nvw3j`V$9aIf>3bxmM}JRw(AU_wGHQ1Q zU_RK+Ql@lUX2UDL7+lr zr4RU#lTeFKKhv~e8LfDqj6^7lP%u{%O%vxAN1S@nFI_Anhe>#?2dqQ>%5AlyN0QAr zebN>_Wkx;Qp5ZK}7)LEuzz~~Xrz4B9`3UXF6JHADVG7$Tb7rnC0HF{2dp2}k6p=c8 z*O{;HPpUBDpVZRu#?$h4M&QPp{4dMa7w9iB*vb4O^DqGfle3YRhwmO%a%fy9MJ18u zm_2WhV!M#%1lmO84G+RTHJ?ytM?Xmmx^WsH1V0+VOma1gyh@vaoG>e1o-uz{=Vkvm zs-?g%PwoB91M!PgQ&qw?clrc#LlDDK2%K3C-l`9$Nt7rP==JniMCr~Q>iQ?BvZF~L zVD(hlI9-4YgGzT22J?6(F%qTL8SE^z4cWd+RELF_K{|5NNUuen;73?u^Vb`pTQHtO zE4y_CcyTsIt_etmFpy(>qsp0*5Me|Mcc^=C$b&QLhrtX}_qNotak%9Nqd9+*iU3x* zkATD6a5quBx3JWN{{Eu8a)jKYETl)7>)SXwa|g@^zlyx5D~L;nq5{#LqT^H^FLu3%I(>G+Dql)0rpps4xt`Q{!<`dyfWBIn;&c6x&gxTER&Lmrl8U_u-P_G@C|i z_a{r3>gxWU{LX3&j4fT>y+e;ruQ~}m0xbh{+RmqZ5JkMqf_P!J%iiUzbv?XchHsCD^m27>l_u;oj&c+lhAHH(f%=_H*)T8@uL#mH zICunjVcBF{ShRHjy*S)9qTG=(-caEXOsomA4zHkS?7j_F9xcjFvf+f{XFDsP3sBjP zD28JcN-;MhqL*d2>)bw1jvn;^+2*^FBqZBp1PYPNe&QWo1TjM*eF9MAh_K?(8;{w$ z1pqA|Y^Z&E{mFQP{r0y*55;n;>&Mr04ewX|BmW<(`af!)te%j@z|{=476Y1&ZvkT&wO0Ya6D9i_oR%V%G9NT+XB!P&IxQ zL$DjyS3$09HocS1a)E*PKoeJLeYHNTN?J!2@`Pv03)z;f+unHEU^~bPSGgZwj&jbx zHO^sxpugK@{GPso+iYhd zjm$W9#7Tx-PcH*JbShS4rUennX409mh$xSqkb=H}aeu_{i$0?mw%N2iyCAzw{*Fy3 z0tKzZoS;jKXZDmSW{7=C;}Mw~Sl&!F#-yQ&asrA@%f`MUtH9bIIC_$w`VhgLg6<)DY^LR-;@=~8HFFqG562P04!7?(v2N<*QV#e#09k~rB9C?|mZ#$=dL`pzW3V9U8Ch}uWDWi~(qaM~z zn^yd(8Re4U;-#%B_9ylVj9s9eq4>e8y&8N^e71^)W-j}$L;if%6FRFe=k4^@cl7VS zAq7Jh3uRN6|KpR_l>z-igB4X)Zj_qs=qH-wf43E~7h^0$(f|kETyUQcb#z|V2!B@O zLwTJ-J{A@7OrQvrz)x=SynNXvGxmD?yL!HHicv?AEwfQ+sMi-5B@wf;U;PRwSZvv> z--DfLY&UG@=lCA9@!n@4ebQNm7tI5pPx@>G(zT4b1E@IyfKJt$Ij zC|<+PlL1reaSXOcI`e`5v-a_2`VoHIsyfOz^Lyy`V04)K&_i;I%75eqzynAkEuIF= z>;Ax^#373pvC3lA;bDxel*lXMbBzOeVVHx3)Q**&DC@$ohkv$lMwCFQ4zXxL&}s}D ziOOXXs~@BOPi>Y$`A_Oqgm?n6&TjIjIh_Cm1t; z^H~hzHUPYCDO@lSIvs|BsmXLsk$tr2;O}yfZPl8%<`N61Dm9QQnT3=J>7}!qEU=+P z=xHHM?ouJS4o#`UPZH@?Og*)S;UTnq_LV+OsPG5~@FQsz{-7;pD0sM-6#G;07UVC# z#SR%2y_3SYCG((FM{Y=q3dx9}LckjrSR8H^w|g_A;i}}HM~IqH>nhA5%bH*Wx10RP zVhM@>Ol!e#G>Y?MHAIt~c%d(nJ^UsoE$d6s_;nQRvR@kXeDVskrS0H`Fbqi=cWH3Y z3LM;F7iY`PpjbzeEsZHC8Kx%1Tq#o$^_c?*%g3Cx7yE4FH!`J7E<6cSOl*tITaseR zo&D|-s(awF)R~8MW-gkQ6ENG)U3ft5L@;v<<%>gq92yYgv(8hNiE^kHMC=u=%uzCr z5#Fo{skwA}2QV~pBH{c0`;b*#2N^cVkItkUEGkO?84k@KLgpY9uAhUa7sn(Hmff z4|9|pM8;b}LaT=S%MQ1n4zq1M3Upe$Mc7`tCD>NK3j`uM$_z{3*c}+dyWd6t`LpL{ zp?iVx7P^Hw81x{$L8UPCD@Y?;@Ok^J@OcNYb3H0|DZtu)^xEt`VK?k=L_f9?Z@+0G z81;hICSw53&enF%kD98rLmfmZUr42 zLSzfh&axBCK`Cjz@2tu+n!ihgy2Kx-$#C_IFZ|jr#c?AeSE`#)5Dqe2pQ%|fsI39@ao!v+I zR2<`GGvvnzd`0$MTm@>IMP_PK{7U|&Z1-gyKKiEIVah^U%QvgP=zLb>1gJ^&;DNpkobiz?5@Xq66y+Qa0n9Zo1ku=UIX96Is$%$PpMkYm?|x z#5fexjOXSV(_}SJz0$lxRE<8-pxrKb+JE}`PltAU?rHxnrr`j7{jMuo{T+3&55`KA zKD4R~+*Z|ZiA96DsgsQ?~lq-2!nJ z?)5yVqG(JwXnqYl)#!DS=U`pi(PFmr1R z$^uNMw&ctL>7DjiG95w}yi%mPr$cH}*jeq$&W-#;Y$}%khdc#)0HDr4di2lr z3`XAmcwP576K0banDt+hM)r#-wi>+k9OvpBkt%DZ$Ya)amp_Lva(>Ds&_nafeXqyH zV3L?7^Mr+^V-%y;Roew!V==-=_sFETHIcElhHW(xYas(rBE&gk%j(^*Xmxd_)u(hJ zwLoE})~|eMiSvXih~HLhOq{ma_sEt!-vE<5JL$yM<%=yZMS%tqcqbnhLaqecMqgE*TkFn`5AK`N|st z*#{U(=u6c~%|=@VDz&-W$z+D7+41C`8SmcDZ@YMr$Z&>o{lB3=)1w53yL2!}u=*f= z%81{B>LpKzK`=@^6$Yi1Ol5ESm0+gbR_LUn6(2q~Y)*R}y0JC)~KE;h7;+@G>7(b=NVmw7MX@}85HY$R$fEWLUlntbP> z9y{D*D1pXz&%@9R<1l$wAi2PYu2>i~aIXflx%sV%!HFb*{e`+~^?7Cqx8QnJ8!SFI z0EIZQxl(Ss&E!{Q`JYbcGnHXtINC9&?6ayi8Z}4F;R_EDF${H;t_XIB3!3f3bNDX$ z_*MNY)vjQ7t{>h}W&3C19&qmZStRAx>#=>~ zqueLv`6e1-o*TchcTGg2fZqNl;ITtWcM@>Q`o?a!Er^J<_G{yOX*uLUdQ=V`#!r70 z=c@~sZ~OTtFE50hBWaH*(fSJk&RWNJSdbGw59WsXraic4uAIB{%B!BoTV{=xPPflL zl79S3)f>m^tXZL1CN=S76!}VO^Kzs+U)T%~c)R7~fDb;Rc`?3<+`a}2NP08G4tj$X z8go4GO1H-;$%m8Q2EK+Oe#6^aKcdEuc2K?e&Karriy(S0#Q#-7D~#IwnyAhZxBt-u zz5urW@bvD+(Z#6=c>8;HQSwyXWhuXE2P%^As$;?VViVMoFiOk z`tAc7|5H$&ae#5SK{j^CY}|ndXqiW@kYi@*?iqA8F-}>4nt3~}VDuj<(3ja-B8DLW zm$_gm?rP`HL+6c*qq(aKdMl&&YyaidByA1ByF4&%T2uZ1aMVyW+5nTkUOGNloj${wLyF#zL4} zrQ4=rSQbT3+uZ)fT%TAz&@Wh1--F&BB$fHx!@p#X)Oq8}+y{aaPISRRz302iQ9e7)7N6ax86qR0@iLMG@c~q-!uMydz`2J zTTW`TJu&-oJhoz_ZPMnBfM6S2P^2W8*FJLYW2#3MlwDYw{}G$vW9rH-ESOj z2SUtVl5E{}yl|?~e?(EyWqWaPp2N)q)8RYnu{tb(CYR`m>A2`v7%{||ZP6jo5@c=5 z7eKpa>9L;`+r<56Q7_gg$1bNp3_R@Xg~{-B%%b8pQUX+qjA z>j$2)!)6eO5 zd+}Bj?A*$grRmBwmCWzV)jJENxD{NP^R{PLN-sZi)2-kufQv&goFfNbuWG&TPs?vZyu1@fYD`gvZ$|W#UnPf}o^+B{QEk!me$7fltgB zyl^mp^z0q(S($Yl$&|@u38QhaMwl%?o?yKN6$$dH%Jc9nu-pQZ&0CWpO%z^xZe^63 z2h8~R%2MG&7$jb12GV34v^6d!0j<)7@Z!2F#iUfTYrpstYMX4oJ;ZHmafui;C58z-wVr4ckM0;r>Z5q>&s@VhZwwArK1=QC-_Yh4{-{ zvCC}Oz*1S5zw5|0<{>OZpR3{k0*TH`P8Jq&XbCa1TNh+Lm%qz}m+UCo|KK6iALSv{ z|Glef7oFJ`y;iEc_ouIN9fX8fJolbOQF@C^d1nUBBzNl5_XdEOC%lFld(n=cnTDQ; zvhrUZ_^I5+Ta3`Igy%Ye`3pq5bK8rE*Y^Bp-1$PaCs)XG5-j$07S2svfx?I-5XYryt6ni(}&76P$%HD%P?G&*{it4ZH2 zUEPoTT8V*%j42<|(x2FhYJ=0-Nx#{{0HlnWjy)tiQJ_3`f}ERIH%3>>N#n@%Ys1R4 z80yBE%tU%rcHFSNEcu#AYM3ft{4IZKtSHW>^xuDJwB*mt4B3c^i#f&H3tqc#EQpnAmrx6%8a#Zn)=6h5+8E) z*Zi?Q>oK}~?idg{s+qc`(=02TFjq$#2wmSwCRM$0oaG87C6CR>hA9*d_qEB(_MUoQTWBs`9(k=;sKYb&UmrxIm=Q?yzA?JQ)^Fzuce$#*yA34b&mW z42gG`nKN)4a_Zos`4QwgM-?*%Hd6;SWQo2J#jO5%D+)YxF}(^~*#nDW>DV@H_GZ@u z4KJfqZ?dxeIUlfVnXKA^77>dTB>&$w%QewY7%l*FUvG?MfNNGY`k^PfFVxZ{rlMZI zCi;-SC&Hg8^A?0Ek&k~lKQN61qL;sf*}bp9B<24`r}$?}TB2d8j%tqPw~fT2IRc+1 zEhdHxS6F_Bwc291T9)=zHs^OECq;2?>mEx0G3ArRA#M52? zicak*&Q7&N=Uf4@+W4+C%6$9}zAo#O-ueQql@x|Ri0wah+t(M-K#`t9XH`$RhWnI| zXvGXsC`q_xr7cpX9qpZ;mufyjm(-O zZjX_Kx7Wn{M4&HqibMgQN_>*9fx^iFq}I@9Ke=P*bFBI#%as>Q%N2Vu)~OY8V=+~! zt%PiA*Ux28)H3GG=&2AdR&}NqesY~kLr-}wpjcZgQ(sLu1(PNtsj@6p^oiPgK~-Ja zP*BCzBL5hCsTv*!kxU&n32gO&RZYkO+b%v;TrMZ>glvj0bSJlP20%y*C1%Tg@b;?= zS0$DlsobPy;-Pku_Zu2ln#kpst5$+GpSfx3$)G(r=VU6~7s?t4yD5TBiv{K{Ve9x+ z^A%$;=O~r1BFCl|K=_*Fu2?G?E7oB5w9#aNy^j~AK-l?nmO?I~P#geE0VH{0N*@m zzHr%3Lv*@{${W+EJaY8ZHUNKA&+j1{l3^&e3NKj4w;O;dvg9^Vqb9HJv+ifE7(ZzS z{P;tf>gvsUtF|ZUtBM2%5JTlp*Cd9eKtWCn5*w*Afs(kpGUSG_uNW-T7|+D$4%ioB z&=;iDhV+`s0uXp6b0W{|M2MQaz*!1JIWgN{!Slj7EDpIaGyD zt2^qoct_x?o+N1N!PBRCjmdWW?jPbldQ9zJRatvtFsrw}xlu920<_p6g%j^AZ zqw7VDsT`~9XJS!__ta$wmxnn9iov8x?ZXms=GK#kMD+U?E0xSD3WUp6<@p&|b76DL*sYR)7{a?-w$Mo{6 zCiU%5;{{pCC$iCYvp=?N;2nyRkga`S9yl~+L&T%ZCL%LQy|h^5Gosicz;(>6u_s4t!Ozm1 z$z9z*aW?YwP`O1pug>Hb9NZ^_u*SleahE^PCl* z=Rm5Sf>XlIjw6PKnIlb>Tz!Q?;1&>136V8=6v+Q<2{ZdqGi*ldk)n2c*_|Gb)0qWk zWG+8q2fIC~gN>^E`-V>$`~6M3o}Sg;k>)cG`&IX`(oo{~S7x%F=3!J|N=g1O8nU3Z z8FCV9xPt(xuo&)@-3OmxM7r!+-;R#EVnYPZWU|UP5lAQpA(1l6>1h*pE$PL#+Og#@ zLr-5Uf6Nk(o`u&#>MAb>Bcy z6#sy@4;h&8F~SS@J%beZ7PN+^HuRA)lz-DS$;7F66gxMx8st?`v%u$zuC zsk*+U;*Ys)ptl@AnvPbe_F6*Y|ymUhb- zUEl4`U)$Ap%pkUJ?JF)YOpH`Gm_&7g^D6KldRYR1E?MrhdlYep#9#5?;|oZ0g!1}P z-U)Cb)A6gcN%Y$-zVaT(9k{?fkl87E9^5*mD@KhB-%L1o!q}}8X z&&B`ifr9i)0m3eDWD{_Z2tpSW5@)S>faeJyxxt4f$L4TQ21aV5n0fkVaoB_3Qrzt9 zd)Pl5<3qb+`3z6OiCFJfxQRq@{-LK#WV;W|_S15HY%@J!FN-TM^|7#_L(Ynfi9vvq zBR2*sI+3F+6F;~!u?Y%KwDJ9;~YHh%aC`vpBOR)#@izz{erL(876_XI*^6E#1STL6w$* z9+9>v5@CwZr(XS-wh>|!9~rI~T_;4bklr3UiZ0A;nS}d!b1N=22)L;6sWK?3g`zz? zPQ~8%MahwPMlaBDq2%;V0WCE_7G$l6Wn$+EXdGXHI}x!~u-uw;8nNX==9^pcoWfhlx;ZMA+50by7&dc7N3JB^9 zr}aR9q+;iAHiOQie#LWy)~Di(VnomGClYxWAvcO>b%^NXGCX{WN|hRY&cV*u741>F zW$!Vx_+_$~kbvx(>UX|tV9&p!O;^#1?h|!GHITQj4gG@V6GzC2^9@2>G>r`HEj$lx zQzDy646$M`^XIc@ks>?J6}o=~kuxSDT2}yR*O|G8nX7C;UFKcvl7c3_h5QT5)bqWK zb8SKG1<7E&E6i+(tLRE4?}d>Z12bABbW~%!oke>hzjTQ=E_&k7xoz&0=GLBi-8qyU zi*o&R!Ymo2!Re~XHdFMc0Cg`nW|pwXMcOgFSXvLR5YI2dmGCyx#3#92N;tF3PBanqO%!wvVU4v-g@p^(>Y= z@n&AypJ|q8LTGT1mdhe2(SQ1k>u&KX2w-vutgMGRB1INyYT$f*@i3s!rgQypP{zTo z_O7{J3G!W$KUC^E{IAnZm;NotwM`s zT}Xt+DtAs~(HT)C?1WfA%Pk>lP1ff*t^FqsrK9wig3u#KENW>S4||t6fi?{?LcCmY zv}#OPpG28u8g3l%wIM#S_of{FR@!`c$D8ruMX$=2g%P`e8?h#JW!Y4?M(2P8M+v+s zMUV}Y^%%J-I&jcbBL-`ru8%t^B+NC^OHLbs(LlS<`&$emErLfff=AV50E@VTTw4WB z5f3r9sTb7CD0qnUL-?hBG9KDs`scY#%HHaJOmRuO9yT^l)90bGSJ8=R&!4tkuP#7=0sl zn#zT6sovB|M*y)YXo;P#%7x-kP`M(L;FGDbqkwEC3RTk?sW}oMEalATgUEzm@R{#i zN`pA2{rne-1R@q0t>yp94Wg_fjp&OFE>ax>p$HfetzBlAZ>u5$=6M-b<+3VV)mi z_wXzGZdu+e|8Rp~N#^ypIpgiA+Ft(+s-YBE51~kp4YB{B-I_aEHVliBdL2b{KIx!B z!{`Ovb{WkjKWDMA8R9jM^BIt`o2s{2Nt6530|#rZG+gN;c!n>R#GZBNb9h5k?9Deq zXC_P4))*5*c@LOLUc~VI&_7%IhZ#hvJ;wPz%pgZjd$4E8`PIbmKmZ$41XZEBoPIxz zy(F&$R*p?1lVAXOgSgA`cpD1wFFHhjczfAB?R`3=FT1B8jarG%Gvy(@{~!xD zeE(wY`o^heB0IP2^X&sNAnBDk0<5i&I7bv*JrQd-9p&JuEz%l?Us_ms1BXQ#K;@|W zQ;x=wG$PJXIpQmmpuF*njDMJ(oPXiAeLX>{n5jrqEh787@?e$VewC^Ac7R}0wXYJ< zkHbSiAh5|a%Qy;_wUme09A?uJz@w>|o?KJn2bsleKTQKoMyX?&1~c!h^UZg)Mb`Zb z5lo(B&UaSTXwarsufY^kb&wj`s=_8CZe}#=dZctw;VFP{{0m8bP^gt$*mz2< zP|dy-J2RQ38FwCG6fepiJ>_H|c0#v-y4or915|7LK?oKPHf3!(nzFG~!gS6aGfYNA z&min1+GJ!DRNlOTR_CgM@2btyxaV+Hd^q`|XnK;js2tdR?g)0}(2W$E*|fAtJB)_$ z83u8lvOzT4BdZ{lCbn}`Wb~)<59*PMxoL!LSEmBg@x-XOoR`x`!`Dj99*55rGk@q% zwu4VRXm`P8n)3ZSEY^l7nZf&v{SeLp;K(tEnq}EwOm6v}`F$r!Z^GAiWHifkVHP{1R^-*=Zn4CY>gWY0m4k_l0M4}G z?&&gKVG()@0;Cwee&3QJ=*xD0A&`f=XGj-crcI*3qeP0)ws&9!r)TcYR`Z5O>F#+% zdGzH~$k0Q1)UvDc0FNK(bR8il>926B=&k|%2RbK#)Acw=Y0d*<6E#A(^)H>>JqPV4 zhw6h@T|XGi%gu5Zds_X2y`9!|7sY}G3&#YLgqr8SFv+%E5a-)9d9IrfXPy)bct2&& zzQxyBn8q?>tyf5Csk>V4DR%bVPcj`Bd`KK2*k@??jQJV(gh4T*a2# zw0>2G7-KUIX+_ar)YBKqIdMzltg%}D+B2>tDIxR z%dk@YPJCP35LgpGaO9z*$Acy}(zPbv4}1Jt#Rq~XwP45NcHilG8d}F!cDRYf`fvtIS3h_Mh-#v5pa1_}MjCcrZXy;uC#hf(@P?%$t zg>1)xfmweS72CXmoMOZwwN4#Z7%k3hG{r^qt7y@^gSKc_i+BD@ag zk~~|o-COg8YEOE7?Yk2WN_oi}Qf`y(VpV#e`A)J_kf=F4?b2;i=5lKxAQ=wL=t~^h zlV$XJj7T9zc3B(S!7<(V2Kn+|qO&da*|6y4rk`-SW00Oiv@7)c#A`r0_D~!btf#vp zI?)NhG3DiV-{-r!xX~AR`VKD3HLD>AKPcA>OE3@{*?9Lf;-n!@*pdTBHgkPZohYDc>CYf*K8~J^8_62XGv!D6tk$B{(#{jMfD>JMtq_S&?K65KV8(@Bi z$I3SYV7z@66K7=h%9x{#)-!#?DO$nq?ms0d;=t}6KD8CUVe(3w^N!wD|Jr;oh3F@c zXx$9CUW)~_%`?TGz7DzW09F$1j=KYcI%?ASP~0X>SPVmqTaxs;?uz$-MSPuj5`_A` zX%(tMYc(F5;hy6DL)YdF>|EfE3zCoKRWG-(SB1wQTyvJ5vEy!5Uh-o*#?fR8+u$VP zlMcFD*k!n)5(kc~W;m%5S$4i-ZUFgo40l}8ALDEL0dkeS+U`L34)dSpH*o~v;iE7# zBJ8>?tVje-wzS!vay4jI6f5YHXDsxjEZpLih z0LVW;DzeE-_{_uAinCzpU&CJOGm&q4sbYM5KQ^l=LkU&#X!sQr5_?EA=dOT{NnV@< z+F*OpkQL_c(cX9^g$h%12;9SsFF3|)e-wWOvCq;7Q#=-xvRCC(BpQ~fpsysG#Q&opud#R`(z`fP>V`uinL>AVDD84wJ^@4%_ja> zVCi<7hjvV5TUlVWEzf7=h-5iF>y}N*qxr$&#-^F91aj@B$t&A2Y z%QNQG#I><)jhkW=VT&+q6qy+1JAPi6WlKpf>jHgq_lgCq{8+(gZzfx$Xn5fvT{(=R zJqvMTXHV@Lx<4Y7^4XuwvhSUnbW#(0YLP^qTppstx95d%%1iyFnjh`$z=EJ0vgSW~K`?vbpOk(`e(}na zlBd1`_nfkl>4mL^WVYll+}3qN5XHzY?1Z^|z8g zJMRH&`M~23BhU8=$ zQ<-6r3LDHc?1-AG*i$(c!IPjPndT!Y-k?P=dTJI_gXjksu*=ahwUG zgo)=bhAgU`BAF!^+dHDvhB$WUybId#=D?;+WGXaTi3eI3#4s}6l)R%pLF82uRqP(K zkRx8)Ng36QNWC-4FzT!r_o;P;vJ3~)jaBMh1aC9i;YMJ9!1dawK8v1 zD9~_YL9}6m<42j|sa|6aMJeBwU7R3lx;N~o8be1I8E}ov0hVv6Wp%;<6=)R@8W{sL z-_*+L!~>eCt5AuOg=0W2Y9n!5qvqk}troms9+-e7SY=KEBB2hcrGs3NOG%5SCqLa7 zW`_ZeX~b}_8AS9oqJ&S+IyS`{Do``;|9VZ5A0T6+oJq8|mZJt8ewfYv(Oks=M z>u{2^8LZOEg{5Y~Ne|mP18rnE-^|!79BU0*Y$6Y>YfRT=7f_uDAyV=weZIf{a%@wt zm)$vO;(JvTXXxLG|0~|@xN+`GOO+kpppph@XbIdhvRvkC>fpJj(?f4?G81-Ltz4b0kD$kgCUY%cHKTfySZ1t~90fE{#OPnm61T8VFb8_xVoSOZ1Fo#HN)L@~v|e?{~)| zb%n8B196njkU@NkdBi>H>R|GrXfocYaQH9dgsLENI#SfcB(t%EKj8mUb`MCJP1paD z+#SEB(*Mi1#`4b-JtbM&9?lSJ^wYkxv$3(X!+rqqIq*J~!ALP^6T}G=-dyOVy?8)O@bH zG+i5Q$Sa9D0+DGA2}VJHZX#6A?tWW|PkH`ip>8egJ4{6&f0Z6KE?m_n%i> z!*S6vkV$>Iw6&~N(FO1nshRU9;em}|qdVw*FtSzC9%L~c9!A`SG9%Qkq5y!}EQ`dp#a0|L124ds?>4 z^i^D8zKZMrOVjwz;wo-wYGdO3-vEdd#fdM32O8gkx{YmhbzC(SgGzCuwp;9h`!Y~o-u~r9~;SEGUx=X4#i(v@6ZN_<~ebDDWq^JQyFjE)2ORiPSa(I{W zg#y9fmp&v4*kY_G7M%*C zX_JV<{dgsaG}Lr>iQf<2D%!NY8;sR#_CY@Hzlb4Zz_Dh03d zbzgOD8ts`%Lm2-4;rO4=zdvY~h~n${pMU*v{@dZte;;n*_D;5jE@B?WrVcKa_ICeS zG!JUxYkD2*3Ih#UDO0`0pE*Tr5T5Vkk9~UsvM3#wG+4M)*?UXn91R}+@#x;P&Ps7jQtf=*abjjAYH&}iB_Y@p zyfYBcUP4vMJ7aV*A%xbAP|w7u?S!$6g&E;j+lWd0U=va8z0W4)p&xHa33H<^du>S9! z{r@HCssHx>;vRf%XN-4^A3~5wJLnLtqBXF5vx0>dCxU(SsuYfJ^MAh@MTGb`6)o%KqK)*j{W#sR83171G~&y)`wiDg z?gQTh-@~s^Og->hgg4e`3OpENE(FUq4!B;QF2a{kM*)KPJ+S-VLf8a!Up_sw5kp?I z<8#9`Z&6OdrQ38MsiDfQ0#w|@TL>H>!k$z{9FQ4PKH@TN>{hY;-WZ3UU}VWDi*WSU zEgL`aASJtxv>U%JaAvpBY3d~8{DI{k0i~uNi8cbHDx`)!*!l^3nhC#Ev3n>6S4>}l zKzl3B8YG>hIuy6cpx)9J3F6t*$SfFV9+cEIF5X3JvyPZ;GWTQGVk7Z}(J`{ajSaX} zu!t(*HXdV*wPM3E78tKi(~OLk;)JP8-YB;rC6PG*Nse6RoCeJS!gF9#MvR-Q{RKXo zvD=f_2Zr>;L@}@hH=|0*vYVajZBrg=d`O6uKsT>0dh%OZONsI9s<~(qaEZ{i)uu5| zyID+U8rS!SeFdY7B8O%v)!D>)W1WjEU1$a!xi2&;wz@|8;1Qll5w0nTA(c#xEOZoy zPVOkxAG)i8BBv5(Qm6h7@IA2CO!}9YtO>Yld${YTKIIrnvRp+A&Se z=nJtzH$&&nIJxFSR<9V}>XfrOTU=?Xe!<7_rY_0}I}ULASGdQ|ol85pqiaPbr~P`A zfNZ3u^-9nrDjhpoWH^$_O1sfpk`UfgP0v$DNYWo{ML(7#04OsM`X&fn?^qM0S16_B zNNK#IWc-ajWZJ@U0(Fd<4LwS|ivlw-rP1HJN7#rkY1;b1Do0ayZSfjAU>e)vvPITI zfH}oaDs%oWGJcxxO%Q|IGM81iuNbv75?q=zVPyL=NA}vxj|&t%lR*_SG?N!tGY(Oc zG7?9#sZl2?3wzg9knRx`rBguD)U!%NLuT@#y}O!mWX&mriJ26!G@*SscYkHCq@je@ zEo`Y?xWjU}2S@sG%%MDXA5yAP=b&!IiOR}BQLL02M@Wx4dZrPW0<$v35b-28DwSO3zKLvf60+ZSJBdL z=syYAfd0t~TMGH`XHS%cK|b;rT&qiZRQ@g!uC{?e1$&LgnloeZjrHr+ z@s1Y1)d*6*f>*KRV1;u=tMq`QaM%8>V}L!BKmgx<*S+eNyW_4Sc4xx$E4KHb%jQ!=bd$uRYR)iUT>?b}CMIn$nh7Qf0Wq{h?3l^g zR1O8R$I{BLF8n05jQTWsWv4_;P3i~u@FBuZybH~ROXL+CObaUCb!P$B&FBw)n-un| zW>0O5Ud!PlPW|`w;q1wDai5|MLe-^1jIXryc^&lBlYijyn_mFVTht!wA19Sl)K)su!J=ySjnKuHI*Kg`JwUD=PMP~~RyDCKcq2J{6T6l$)h^M&-z2R0gye$$8Jn0=?ccB5^d zny+ATP*^>yXmC>UqBbX!ON#?3(OBi80An%MV}*$ih zt3In{)Eq0!o!gB%?X6gma|GUExY7HU*^Z^vSln6Z2p*{27!4V+)I!XQx?Cz(l$ak~ zxS9F8#AKE5tEc&H;2d|05?qKzsOx*9W{8UF*BHO9cBcuzKcm8d)tCY}HxS%siBubPyD0L z(rHEmr9@ukz2LBa@#Uv0niCCHLSeGS6oFs4${L z;BFc7;@^ zK`2z(5~IB-O?kdlZZH<%CXj?VUHwMcG?&~pmAH&EbU z{r)s;fRrB6Z)kMO#Ox7*#VZX*K>A%Gy#HWm7ux8SjG0p!E;kbytP^ z_jw2f&%7wKM>!obpZS8{lUUa)9stgBF=;s5FnRm|9 z*`3hNoZkd6&VpsqepN=NSI(y*oRc?%Byay>ge%!ddCP?a0kKE_f5meBcdPk-+8yVA zwwcxHQQl}@{mvGd1M9&p3|TlLRNZ+4^BNKnNrVPee!^`$JT;XnMQ74h;P|DR8wP0M z{GVlhw7;{<5<6;tVUQE4&~GCOeP3I&nx73n!~OJob9ovmcrLF^)H`?Fk2k$fHg~=n zp3xk>_nophFpWt62@BEIXbPL^5g2T~*M?}@RR)3;2c3!f-~(E`mGSt{v8SLLG^Yxz zr(f|%DM-N-MTm~r(5EPFhOOXW?Qpsa{_joax>n`zGnJggVNR}@dY<4MtgQac%#Hvc-V`I0AQ(CqAQS$SA~pkdk4LVHOM zsTFl{lv6_{%t!h}oH{Buvtm#)-6NC&;E(W0Z)CKL680(#wnz9KftKdV8Fi{H!Ja*g zWFqXA?x4eUJ>^~;iAQI7izkKCPmrcqub)3{8Cj9hXhIO!Z5I-8%;T3VRAkD)rlzLg z(7_(#NynqnmzK{+?n-^sehf~6 zF7-Q1zn-T?TVA|tO;4;HFp{>EWZnILjJ;EICQ-Pq+p%qTY}=iVZKGrRk304s+qP{x z9ozn6C!LOUa@N{=pRv}(KC4EJIqIhBs_L8btNFgqyM(tDZUsrDEOlO9qp?Wufhw$Y zBPvj|Yjg{{j}{||^#&_^^aKpd1z8XZYu+FTOy33vVm)z=IzWChj(+Xf@ghgAB@#+P zk{scpz0t;$LVXI3vIpkw@{HY9;R?;%2JSLDWud=eg?jFnxZ#IlYa-G8;9tQrt8Cwp zyW%_-pND5x1awvGa=wZ5lY~_Jp)1t_x=5dN2^|nVY62f`aG=f|LjvWsW@gn4m`&4! z>@!|7yzcOZ6@MmC*))~q>*z4((nq%o4hZ_mEP@0b-QqQq)UBor4iB=g9^Q62K?Q9r zngKQ$k|J(ECS1(avYvWG;FcE7jP-1mzjesfr?*|^5}?7D>C z;*xe4$dEFy;t0=p;TKDnmVq7ht7wkykim|9b`W5#yc&8NV~#b7?1c&$O~xJN_|s;x z^9WR2MqMYm8Rc<1rJnZsOvp#>Bs)n35S7e5M(TbEXKDKo5h*A&^he^|d2JpN+?O}Y z3JV6C?a&lv10Ls8%|X3bgf@@=GxG=uhk0%y>tC;iWuf{ivyXB$Sz(ZKz7# zA4KPjtJ56Z1Z8Rvj2Xnl!e=*V{)udxrCyvX3wJ%nkBNQnJshFvUcGyt2PB)7zw&%Y zM9*3L}c)fS{D#tQtN zV9ey^BlUI5uv8TVX0AoUI#L*WepFN18WgNWU})w5t8I-J0nYl2mj7wj+IH0XMFcfR3`lx@K;DRHv&aH70trZ zAur^CGsd7YHi$6f*Mr~#5~_26r-WG3g()vBDRD+gBjp>(3Bd`i zx+2a$n8dZl?pEQO;i{ets~HcbEwcokQWLIfmx*)s!xp<1L0-V}@WY276{bYz#YFQ- zEEb{@s-80cAh@g?6lmIKgE7L>06Bwx;j^n(Rgv|qyPDEV!YuRDR8!ua)&`yPXNsi# z{Fp^GkF(>HSLA^S4iYo=p_@w<(-+GGb^u$@F2Ao!W0K3D;)&6cWm@{5^wF3jBO75W zGb$6!*%mYck5IEkU6|%P#f~wiC^ID0ggp@NT2~lw`v)+BRZg?UtmUXpa{A5P2)8aE zTj~>6`*VgB9te#uJSkQYSXLvY>QfCHRdEfO_rLvyf?2cL95)!wzG(g;dy@I_HBz%< zEPMn_CFhV3p}Y@INj$PR)t6JdKnAF;vIHZXBr&-toF-hLsiRMk>PRi(;tz;RqIn=9 zSYooSoj5gn9jT zz8cn+;ghg0gA!sUx{MVgEh3$8V4K8^zFWe|tt#9c5a4H31FON57Yp?vPR3Wh>X$l10lfuqKC z{olFr|9igwUvs>!ry=GN-e-?w!k9f3B)C)|tVj(iI2;%mRXjf$3m63$6myDc0)wsF z{#B@`?zPv-a)n)UShYs^as?z(s)m=<7us@TeR(^qx?1qET>bR1+w=ESPj>d|$KBCJ z`s4fd{4xo?^rxbjY{Q{zq_X(-=r(AtwF ztB^+2pl@0*%=1w`y5-2AkU*ehyJr^llN77aUJ$HrJiox{sL2y$NzdeC4`{R&wBmse z`I>8MIXnSVlu64fSxA&cyve|s=mv|;8 z{~SYk{0iK7!g;Fm=$= zI*U4hT8OCpgMbRYofb60B34iG0Q(Dg6Nz3j>HNbx09!e#L_|EDbmVD|jWs1jCyBtA z5D;Ce9SKK~#uLD$CwGv0ZB!9hj*-p>ESHwco?J97DPd6`TU0AiFtWy1T}aR9Uz95` zXH_3wv@NMf&lprgQU#=EjH*?Wo*}aCpx(nCWjL-z)F46`v(lS~L%~vJ&wZJc;D^ZP za07+!5%Q}z(JxVkbRS%_A#M#RqIPYNbn>sXej9$vFO!^yy<6`fdvBiG?fdbk;xa<) zlB&nOFJj5frDmsR@GL@6k&TPBbV$5x64aDCWPKT5Udvnq*??-@jhK}2%_%mq7hIpg zrxOdM3VsLzmc217d7e_FsBXxhfz5jE&(=BF7Kis39la@~U;1VI)%V--+(K@#YW@B{ zhE?j-GSW6Igs_yp&&%4K7%o<&OTvBZ)^MYRzpZ%r0=t`Nhm0}K+|n6kW!pLhQMbls z5Z0?dV1GLOHk72mk7Bn0un-rj7_KXUJK0NRVO?J3m&cCC zXY=LhF{0ZklB>JoY!i!EoMzL$F&v;7=Vus&6kr*3@8r`WGy87%9kXlotVUntg=EX- z@m^pH3@Up|7>8}Z?b^7gd@93n^X#5UTjUpu+y;w6(2owHBK>-wBRKWOOQxV(!!oz% zj+vOKXns_ZsDwjKOMcE{XW15houA)7z|a|cR=5gp;gaOoZ`Op82(boqm?h3V0mkwD zmN>xc^JY->cu1~F@>KTWkSsr_sOA7V>6rHPtg*w5>O1@)2O3r9OfC^NFqmc3u9H8( zl-iZ5L|OTq4Bx5Hb5bw;lKBZ;NU21k7X~Mo%ovM-> z(BGE4i|%A?-cB?3eNEw#sv-3msVfUpoOVyet0>SoTO#&v5n5q5(VkrNpHqZ`GwFt= zVhRZj8Mh`r)N|3czA5jQGFiqo6GcaqcjHi`zhRZU(o|Qvz2T_^G(BNk-~$8h?5OP? zlr_^d4bVvUF8`pgr)m{5OR`ZIeccxhJifPtxjd_Nd>)?6VMo=IrfamNsw75h*s_S} zww~&Hm2$X5Mo~zVBm|lb=jBOjEB!gUQeRUmbs;={>m9L~5Gx^_0F{f~eF|tZGiNRWuf zK;$!)(p*qtA3NINhc#&NQA7i#eikl8oT#ZIR7}}n9+|JVN+n%z*CvhSsQj^oDTfhD z+k?Z%r!0-4{~3SjIlQl+(xCcx@MPK=nIhP=rgOb+_O*qJAt}&|M4rQgSQJI%DA7@* z+Z_&P@i>(w;8=M8>fVzwEBDvwyosFw+%dH)lRNGfYWSmT*^f)Ex-)8+sbxc=v}wo2 zThuRhY>KDhPSO9;PbG%x+6pG1G^0mWH)3PzmpwP?O&PD_4-j0~uKjjMuSi7m^#I;g$gS9D zNmGHzjG>kWzV%lnzB0rSSKqiCX|}Ln#D6{pV>;>xBzsDnJSaLos@m$3aCy@M~~Z+t5?u1VSy(}rJh?^#rk z|Ks!Fs_!31NQQxAC-%u%gK_=oy{qe+%&h7Z*M79E6F^g{yRnOA16m?Zw5T_H4~J$$ z^qD*8;5zP_MJGrvky$>RC$?VB1GUF+VE+d4=aiJp9F;fnl_YLyy?P)GVP#+FI3Akf_=z3*ozt9?u*MZ_e^FzY{;@` zCoW$P?Q0d$43d*sqw6HsU=W};Si@O0Qy-rrpnojM4?qqzz>I*Xua5x85$$*m#i{%oWLFzr`U(vWAsGgqz|AAmYjsF{0WOGlT%CxF2Z6uICW9tNS0&&b~z+zPSrPT_sq8(Q3oPGW?4t!@e{)Rcf0-Kq+9 zajDvr;BHY@xk9a9ig(!MYFU>(eYzs8lq{P}ttOY7$_!R@yid{neX*)^TuolgT>~nQ zNzEY=Tg4B^T<64>ENq9(cg_i*&6{#`)p=WQbrY9mfibg?M#O_f} zT4Va#K;9fkWO}Tb4zm8s>A`ET$Cq66D|@Em(N|TET!#bt5??p{P6vZHa7C^Qz1H~5 z2!l93cM-KYxBOiWiIsC`5v&B6<(@`0mhB!_HI|iga*;(9CY|rkB54USt7}^Mpd69W z8LX;gIv+er;tC+tE%@(+|D~O>l>Sk)C9QEr^)w3>u|*0B&A_RU zZ9$QJc_~WH=C8=jWuryXr)1{b7~74Ofd&5}Q|b+q=OF zMd||7y=-V~;vJ!=w-sw$)xz@wKRq4QMJ+&a0Q|7j^g%PC!7($#-$&J5!^!_9@{#LU z_ajTRwV5K6c+C>7hbo%=PeeH|mO;vMQ4(W|?IG*>odDrFH=d&RF~W7U?ZH zX;^%I98rCRxIfbCgkof;U9FS&fY6ma^-iS5LHth@_?9VN$i?scAI}Ou`w8j&7ZOwmSA)?13N7qdA>` zzf*8qjC|I&#S4i2v_&Bin}bj5*RnRXOIJuOz^Ej(XB&nY3X^k+v}C=t&Jr8XNZ`fY z##*ylY8iva|Gdnj?)wN<2~YS~WES0&VQOPUU*nZ(KL(uYmVUbk>_7X_#&0@YvLTqM z=gt!}r%iSDF-tt3?e6xlkQ|^?MouF-VX33@iXp15-x1BQv;ax#?tTrU+8^Bc;|IGp z{>Tq7&7E)G+My*hg;Q@&&h{bVx`Ya9UYA^@^ij&r3(sECI*=>RMO+1oYQmQ8!#jwR zS2XaSojd|{K8{!6am6wF($0duSHupKF~a2UveIlSK0*peUs|4lu>>9Dz?rci#LO`- z90f4^GbqGDci9cvFQ+ zO(BlaqDpU4=*?0>nVD3naEgN~hf%o!7FZI3_eU1PqW(*RyMVtd#kV*ZpWGCmfSazI zo$G^Nas8j*-l~87=y}7$BYKC9n0cW~FbYVK3Ltx`OK!-#B~g?s0(cl9K%F;&aJT5* zzff3pAm*~bZXurX13k1wvJ^7=b&pKKc?Xq_zSNa1wL(yRi?O?-{|MW^%gx}PsXY_q zHN7a)5Qegb88HN6)KJRjs1#EPC;Ip*Jo4eL{Rr5^YmB5^k0k&SW{JA z2bV+)kfs4h^lJNSrFTdOjFSd@N}J?O2{dmtv0^gmY9n1aCny3NahuDKgzxi&>VhDO)m~q6X zRIpF3-RNS6Ko10Ov2G+B{F@T6Pfvs+yqo1-qoYifrJYdsq$5UUq1N#C%iyHm=KD*T zue1`5Oa_^kbuzqwxGQ4Cks#euoZqKwOQLm_xcKWw0#KAo0ObDi!Me1oY>CHpnuZd@Z>6}t{5!tDKHuh8d1y)NpF+C!QYxKWE;vH7{h zI@N?h1?55PK{3Lwl(W7eXToDd?54|V)4tJN#ABVURAL6lu1h5+aJ-*fL)LKhBXGC= z*v4c%k`VP8KeJAQJ)|H4wBi9P8yuZNMLVtn%2#}Ue|MUGYnt*KM>Q*lJ5z|?Z6oMV!fM_#&1 z=QK8V|K3X_8R?aXOgO%T*s2{jCw$=$AUxfd-h~#-CmZIKf_xvzt6Z5-)`(@@jO<#7 zd_R^|21qF5gmw>ZVOSbHF5CsmMBp@eg;G_#!V%ZWo5Vi+RxXuG)JQg(cz)SIHZJW^C858tdE z)*&ADqNcF8kXR;*`IY;0ra^SJz^j}}shmo`h{d-Ea4q{a1MFY}cF5$noG8sK~zYyEt+JnvVjT3)z2&^gKO{0QAG zuilVkkrSIZq(&@5e_Q_470Kcn8x4?lLK=vE88Hwv`&xtRXO?9(yj>>pr5>rO@OF&sZj^%RE=0 z&{WSmS3=)J^z~Q@ok<`UDYZ`W&y8}?4VpQSLQ_PRC4fQ)_EkjpmB58eeyr@BQX$(Y z>g0JM`)#4=4ZIkU$wP^GSl4 z$s=rwu{DGs}HQ;Knp~;6v>T2-NL)@9fZrixiz^i~-j^2TE2{Zb-TZ^CHNn4)-y>!Y3x_-1nppW>?@%K6PE7eCaih@!+uq=RzF@RH=oy<_jl& z1{$RH*d*8_!SLQA8hqX=o*i5+gXdq}Y0o)pwWIa<&jHB=^2pJ3OTr@QEd)QCjCas5mwq-n}ygW_*9I?x9 z)mW_tK|lU6;9rYFKm??PA!p-=DzP1F2&kGfzWEw4?Qpv&Wr!@_k4vCRIZTP{$MwIv z^Ojt`q^MrRi;NvwW16VVj}-**Rp&49AthF;rW1?Cj69b0PhtL<< z=d=rXgMPzy1AjwzgMY)v^2L|zg6k5OgseVNA6L_)4N`|kyRm*s$6J!A#VERVCOmar z4ZW8Ar6i+XxUMx@aeksayKbXfshIGJMsRq ze97J&-xm%;x+S$(b@vlY)<VMPmi1(De|oAvcj^`p7Lkn}DVWljk8iuV#OXMt;V>!81xu-7%^?|lURGj}mk zjEC0)bRYjL%dxx2!g*G{1Nrk1s}J=gF|CSty~T7kpwMxI6>}&r5q*!cN~MafImF$< zbVl*j@lC2#@hzfhEDgt+qWh+J07kPawFS<-Y7D#L>(~LqjpXz(;?tc=6dT{~=cD|n0o zqP}H6#=6aH8-MP^o-@W=0_il4+^y&|HI3}wkvHX#R8d$>I(1BCJOb!F}r`n#2}JmEY@jC}GS(>xiTsT!Zs1zUfta`w|I2Kz`LvSlDkz2|fz) z!&nnOUjp={F9AC1|44xTe@g0qZq+tx+PGjXVSOlo>p8bk_@nm!J%T5#osj)O3?Hlq zw+Sg%L+TGcxJioV%+5VMNjbD0k@rMr*sN8sOpRSxO{V^1WPKf``XT?JzC&Z<*QNER zYxRRg?Z%ps0iRv9TY3)wtmPMEP_H)g=w zRgwV=^kNxdT2|%LTB*&vf2_bU8DUCR_0w7zIn9^0A-Uq;6l5~OjI6q+78K)2z8VF3 zr?t{*bnjVW&GR#|ld3OJKq#4Bn)V-OsTA1s?+rsL#fnl4sxMeTEbDdtTUTJB^+>Hu zm5M_TX}!eh3dJ(rdxw~uwlBtxN~9loFgN9LC3h(WNT!!^F7KZeP+rDQw?O%{l@eX1 zmwc}3A0809ct*xn{UvKCTc(#_;2BjQz%knl&rMziKsbnoTR+ew_lO-Z(9k{wK4?8J zEt*GRuOlH^Vv=e^-K0+|gomSeu2Z4iDDRs4n`hFF9j}nCrj);+Wo<2;t-x#jf!W@@ zbWbc3oxuH))rC8yg`Z=E^Wu;Y;Qk%>MBS_#L1XLzaGqI=3je|8nQ z9-1iKJ{MfA9aGY2zFtvE4)Ld3XI#$u4A|EtGT4ManO`oM$?REX#(Nr7&CVEah`}U{ zH>NRI)2!FY-=7MO0L{Zk7;3U{-+v-3WFi64lXp}Z5UsKY$Vw1hL z9(rQ{yMuKRRdBELM_>O^Wjfxc2X{1Cz2(Y)f;$2d;!VDa@wFxreJ z33FoZK@APc4X#JoGV(41*F0`T7^S^Q)BV*tHVD)eZoRzQ zRdrKDo|}2u_|-$cKceo-0mCbY5T#5Fw3KPoDg5ZHoOF%*7XPeibt_5~7}!QpBak#r z=%oQZT(a;PPR>HTiZig>m-04(XTzsS7`#Xgv?@wafbGSmi7;c09VjyO&x@CR5O`|V z+ozWI5Bm6I_}4e+x9XDd>hs1B%i)?{vpqs7j>`y=j4ZQ^@3D-xZTjOcgJWBX0b6`o zWMx%;5oV^JLke?ax9s=Jqo#Se8Vfh)GQMcQAMYT}TVbz@s0wWV(i1AMz zYY>`ay1&dHZ#9NU$#3xcqIB*G#dX1ApqIz9c6ci+yx|QW*=rqcrzg@Yw52$KE1KNJ zZT2t?CL3X0Ofl2tk@U_;8xp5Hri9V5G*Jic1Bn8sryD0VwziE4{8~Vk_Ml%Ko_^=d@it{0a)Mw ztawXlflz4?#d?2bCWovi2kg?Kp>;S4qpZ>*v&$xHY|%71k~ zJASvAoIVXkgQ)*tfI*+gIGPN~A>^U_xaW8*O|Fu!;xoeGby6fET0vByTz--=wu=2N zOO92hk{`O?jgpLq;9e;)6}kdh*X|zlzzmufF%^aaslcHT-5$q)rhpuEmdI06SbA_H zY^+x}>bBIAf7n_u0Jc*w32mCPNgxSB1NDrU4z3bbS3nIz0`6RJk~~YXZDbI9AS75; zfPt(FST{dtJU|)DF2F$9m0q_v$Tn~oTqscWT~GVhsj9K5842lhUc`#$;V5e3Xic%PfF@!MI{uiJ8 znUM?R-bUmnM*a~6`4RCI4sJUlJQwI^R7o?$#R~2YG`7VtsaKT?q@ohVL8BNZyuem& zihyDnX1hS6k4JAlK|PPd&fE>ho>oC~?3hU)T*FksG?^(F7W6(!w1bynCc_#yK2-ns zNkJ@}4B-DOn(Of-hjxvPe!a|ads9kyE1|lqbVkdFnQe?DE`(B<_O?_d8XLwL%o!{x zP(@iqDR4q6;X$z1^LIhZ9okip=AkYJh5M;09Ao*l%JTc>Nux2w-lY&dK3t}^1_kW( zjrN>e+nR+q!X9=mmM&cDb5&d7O-*GzC~|Xk*O$SNcwbH_kak^8;iAv?stdx_2&Vm& z*wh!r2}Wp=IyR0nHl8wUETPbJY~OSY!*ndsbd0s(fVSa)M|)m0Md0g{O%aex5l~F& zl1k|kOUe2!s{kVLXs+#es%q^J^QEWF6aVEZtL%(+tLHlUnB44dqjdQsWVsfq+1E1M z%Sz7sL5f{^^4|#LU(1(oUmnu`I7q%m69+qH=l|eUGMhL!oBhY&;^}AxV0N{#cVUM3 z_FtDm55-|K1z+9e@E5@R|L%kQkK5Iy?OiC;r4`ivKZW}L60d1&xMPTaiQ?oN$IQR{ z;NaN0@wyorWZ|&?0_DM^85uK_#JcPfDYp_XmZ!c-m&f2n@80dxE&|~UT;6dWO3z8q zha|BdJHKrrRrH26vAMY)`<+kk>p^UW9Gp_v+{mY(gMQ9R1^UH_h_dO)Qikd)0>r-XlG zHl8re3|4VfJjm!S$qH{lHko&D>>Oa0V4K~5;N_{|F89G0V&uME#pa?vsc?K3W3N8Z zVZ)E8v-}mfQ&6Q@34KYDO}CodWWvOh67ACO*43|Xz)^8Zx!}Bj)0om(i)NaZUmBkf zBfE}4&_^(K95xEeVUNe%ps}=64Ne+ORf_%Z+^eIY^X@cCyWqFPm}4kRAPcGvgGCC% zmcBD=r8^^oaY-UzqQ+^Aq2q2~NgMjU!bFqlL}BTBELMVi6b1KvgXaVddPXt-#P*s| zY;l!t@jtJnXa<>%BLtgz<+x+G03%%lgV5X0l2%9gp=N3T`vT^Qd7XwE;v(tPBqJ`A zy-t{5YhRsk9yuT6ZAn%oPEGa-j+w!wR6-l2SJJ5Uc#90;*nz2%yZhNT7MHZdJf{fV zKn{Q?@j6Rtx!!Z2um7T}CN)*ej7wy;q!4E+Q!M+?y!ks?$51;H8}4Rx& zyYz!MN(bk2f5B$r)fAxJ$Bd7Komak{zo|o*W0`trOYdxf)~EPrwCAGY!UXwqVt@*u ziYU?JGJ}|z(}I~7YQJi%Q$4DX5QJ~J8d8ee((2{QLBX20+Yw68Hip7vvl{k}Z*TNt z5avm#-wugnFD4Z5=kLJJ>8a zP8<*OD?C$CN7IWCb+1h)efId|Kc9$lN|f)A^H6?U`nHHP;J~uyBvA1FXh21t=cZ(= z##1CpaKsNn<+r?2c#oPryfLf@jlmy4nbj6O*rr=2fxKkjhLWDp6!lQJaNkFrhwLhl zX)TRV+w)9NK9e~k;0Uw4!mAQd?h(&AIuRYZDz?mbzN*{3Lic_|9rmHPDV)t8?L0l7 z4Z=Bz6~dUL|NZ;D8^`K8tuBbZuJVKd{T~s%VD&@>C+yh~QWa)OqdmC55SnIDB z_9#9BF)3bh8AZE%{vL(T=7gyeN4{_Dw3x9PkDucsgk{27qaK!R?AY0_Gl8As#>YKO z1FBHSXG_9#=$S`p!5CmLtR22z0t`lzJd$XIOU`#*V8U6q?qJE1#;1lwGw6M%M+BoN zr>&i4r?u*31u=pV@rVujT@*u7T3?mXhBeBv=t#zQ6CqRhTG>BvJLQAT=GtLXpZ1YampkcU* zvgQ*Qpz9aV?cJHlNasNQi_P8+`f$7;`LA_98DFwU<||BX^h>Dxe@{gHKXv~<3w^dG zoIAz})`vt&^{|O9R|}YEnfB%%uJ4YpcJ=wIhAPS?FcUwbzv9a{QbwaBj5)v)OTGfv zP7|0;6I!GboAMFtWYEEZa-xl{4jtF8Jy{FAvkMCk+jAZQ#5O#9PlP+3UK5X7zjwMH zyC47h<@yl!eOa&l6`^jGaKVYqZ>7SAO55+#S=>O%_Sp#e2)Rg!PlT;PGu6yDeV#dQ z!{2%^`%H|)ZY)uM9bH3V$HLr-;VOcRaTWK_AN7z6f!b~$D}#5$Nc6}Fh9kTO_|~2Q zkT$laws-O{08C&8!@%$lPWvb(bN!PJ?yphqwtIPOs;5>h@62I$E$`Hop2_O#`X`~! zH<53`h`W+tZ#@3Fu$BVoB-v@Rl+}4M5(+rqM>yq|AInwpzvDnI=AV&bSA0He16JQEH1Dm$V#6nOKU#0E}bgULEpkVfw@9Nl;HlBIzCxcdQ`?|H^;<3 z$Co~AVAUTxR_9F_KQ%MTnwkjFQl5*#trQ<>9&3coyvW2i{+${(XBz4Fo6`~k18B@P zEOfCmC?qrWr#ulsr~=sF++4B)$w7fg>-sk?iTjq8X^lVGXK=z>TKq>Qr$};>T-60R zK#8U0m*+Pl!&4A7(%=}N8Qm81g%7I#q$czQT znT<+F*9r^<%*0TpVnl26$cp@frAEvltHY*&+v|N(L@e_pD-*Gt5^3e>^s^*%jtKgU zt0II;xpXqt{aA`7W7@pp7%_?5&SPuE%4SF!ilQ_F zgzQ7~5*pp{`+fL}uE4ItST{h!a(P3_-Va^;7%q1ntFT~yb>*3P47JIZp?jvHqo$~( zk{dy($y2>}HkWz_VKBu?-Z8BUz8?tf5eyHA={Yl}G171e6{G;jIAJpx*t4{>?;opu zLp2p$P1G`XYwBPXS|f4Bb@ZT;>yj}dnZ35EW4VTX;!N>QJVL2*jbY5PG6AkSR7Ul) zx~^FUUCp?1--_`|XTFrWOg*_*qR7Ye`aeq!d3?s(b7D1Rs+7uY6k%<@=^<1g)z)>` z>J*0<(=cyU5hI@P+#;2309T#K!^~ocjyt%Yn?WlP9_$L?v$wKny#w}iERkm;>gv-{ zXL&ia=4Mm4IkID(qGQVA)h?swO3KO$awIH@a|(fPoW6sgR`3i(7rGFI;;3cb>;-;^ zr|j^ZeH5@a<)PdgDzw&m514IQ(99D8Js;&y^KMEC@k!@%3WVe@Ts(h>2pB=7V<9XA zfFVK-&>7yk8}sdh4&?CE8Q!`2)_Kc>_PD!6wjJ~s;X!g`mWnC18HN)11f#e%;ezJ= z9rmP#4;{N@5(^&urGmvc@%2F^aVDFTmy3_Vu<{seKmNmY&f^)h>-kM}`6(79Hg--A z7~>E=isbh!9Rr}iQ(B< zZG0R7jF)Swh4`O~RHq3-L}&rFv7{EfR_VA4)-0Qz`N2SNjcKE^mt1eMg4Vivg#g$> zvbi18EUW(H%gVwQfZE#w%Rs&%!2XbkIdR7t1+m+!d&7rd1KrF)VtJh|nHL83-hBrv6ol#; zoLdl&k5LWfn?OXdf_kLWvk$h42=ip$t;~hHw>8R+c8cCR%!yBtTXcj^3j#csYg3K6Tb$K*l<` z&YHOLmtn|z$-t#4?kv!&iu%#+`=cGj3scy97-RAI7;V_tmO?R#u1xHLA8gO3p~*Mk zRLL>x)*&iVb#YBWV5>URC`wyusX>si%2q1+66U)KscS$H<7>ldqevt_s6qvJOvuG=pmmyW;N zHA-)U|9e88=Yly+60cb3Sz>_uv)z2Bb>8oVF-C+L$BnV9kl5VVwT>2NreWV5@3yW< z$^j)L&G7O5@37vGciO(ql05~(I+Z*>5PKq@QZV=g=P9_THaC_GUpgHwt|UcH_mn+7 zMn@O_lvQ-6NLO=!elscv*+Ig#ldMS)Ce?%8SX=cdBVXt+L(dhfEwnb%<{?8b8>lMrKtj;3Pb#te?vIN6f&c^kQ8w zjiOI!7m!Q+dq$T%SqF-?C#QX~tkaw)5{{lgE3b!Grlj5x@7%O*N3QmhHbQUrBc+Sr z4~}l;g34e`gOmIMS912`nGlIaAquqbjO0nt$td*;JgT>-1l*k1WK{QAtyapdRuN%V z7J~AHx}_n)=6hjPjAw4wipyZc4gI3#-GIO_TgQ$mon2LI5BA(a2%B;B+GBVx9O;3h zU;(TnRpbKm$g-5aoij4)mWkbO+ve!oz*gPhAdP@(GrCqv3&N#lH*MGI=KE3vk3+BS zwaX{|it?4k5{uyI69AdL=Vpk9W^(vHp|Ys9dubeypgP&SNnyiMJ+)r=qXtllIdwdI zW7D^*Rz}PVT3urEN}{V*X6RA1AUSfW3ae7y8|>^ZSG3QM_#YAo+kj4BIPvN-2A`4Orxo(vTwL=&`te>$9IQfCXDEe!bKRkBB-7~srzrIH5 zh8H$f`Pae@8eGnxOvi@1%afv5AiJg`0Avq){P|cr{HpuxyDg?rtZd}s^svn`kCUA-H${}xJ?4i14;kd{aN($zd>;tmtBRozhFd^Un#eY z|Nnjb|J#VOa{ZqT-UNMz1s2TEU!_(JC1ykrTqE4N)DHoFLQ%P2f3O6om0y@|q2hEp zs#bE!WRE+EyejJTAtn9*!Q2$0j!H90K&hanfc6PVgnfSzeLg+k^ZQe4A?@y^#BP8Q zZo(-I>ytcsGq8Jfsz^7^C~4~o8#$sR^cY&Y6`_YEDl48aT@NRvUsIsPDz>FO^h$M@ z)2N0@=+fq+80VA(`mXRRv%xnL#+sl>0H>(|T-a7T@#Ddxc4jTPEiLZ2XENTFm5Yv8 zXxD2x$3%WJgJ|4?Hz9;d*|@OXstHm8RCw4Qh(=}i(@`GeujXlMcI+4LGa)G+6fhB) zK&sou(aS-5O+fOvZ7lBQ^0Yjbrvi#x!0mSp`1adl6;*Y{0rllF@(I&H)|_!(>Umfb}67 zq~a3w9Ztv(>Db8N8QlzPV%bL$20xrq$Qn~32Y;6-2`arpA738v(&d(XyTdaiWv2V) z=9=zy(XHv&{6mnzg=Z;NHEI}vEGvukF-uI3Ucp{@`EPgh6tiO~mR{2?7QCK{X=RNG zZ6voN`-IMTv0SsL+htll`(ypdvhRPRp*y=X8T@Z7ZV{g+jL(X{+iq=H}5z>F@f0nG$`b;ByNJpj#yy0ihu_Uz3=zG_=cDbP6OY#rQ+3t znt%E(TZrPP$BB?%=MG0W7&2odm>4-@0>J1ZJ^!L(*M+D1XK@UY0Dt}0mMi!PK%e&Y ztF8R&R~!BR^b7ybrmI-P3VSH3iyf^F*0U5}P2z`KHWDg25WHEHK4Gix8A+54W2hNL9ggPtn+EIySp*E*X0-qq41j|Ytl-o!RFk)znG6PIPLadj zh^@EynLX1WBeYrm0N%cp8`uEg=q!55wc9@E+n0SMMgtW;FtG z*rL5#%9N-*`+uA&&hVJ`I|txP+N|Orv2$O-a{NnAIYopG#?XY`7^QU@MbHis%t&G7 z<7T&7wen$8mn4|10-T{Jjj~&SBGy?8Al4UzSD3vgI10ytve~j15(^G>@C2t%ok9ug0n4N3i zVYlO9hbyjyqyswSlQDR5%hcyY7UnNKS6W&H9cwu!=^kXHIGqDv!(7+%zW;s~;%&Pt z5L4P=+so5!Q>gJZglDwiLF}?L&$bG95#ukGXRj_O)WzGUn1d&*UWN+jhK;P;FnFj& z*`Tmb>G(=mGmBm{a*P!zmfdM2D}m%%F)z5_4Ph^@R}SEuAS1}^vNt8HNl;ayMWS4P z<_OLXWLS58RgvVPdrh+1%JVJTvXc#M=s(X2?3*@x@K!oJ-AO3RKqN*nUHznRCHHP( zPShk1c?kp&B7u8n8R05o9obs5C&DNdz8Z6nRvCSPqmUbT1`1+_{X?@?vHDB#WA@ks zhyuK=a0ia@74{L3et~Que_1`@@62YS!)~{v>iboaMqhJ8{XdkwV|b-umNgtZ6uYF&{wCkYI zsVC;ZJhr!JLpJ=u^iUMOx&lOAFxE$=J2Qwrn`0rFA@1&eow85{1CNH~868d@$X4jD zCA08;j%!rW7sK><+a+TAUXI=R9Y4%d2~+lb~#>N zaZ3dg+}fq0ZqNgS0{`$dFJ#U}Z(ga)IXvr$aJ$nAi(`L52pptnOFdx!9A}F4O3RIcYf)-0W9Ay0oCI#M0=^6>2)) zKRbtX>%s2X)J-ncwL_t=FrA)2i}CR2Vxl}Gx}%iqCfd8t$e5vskFG28NiH+vt^`Fs zfYdze?}LeZBPH~qycdaWeKovDXwI|^-RB~<tTBe@iH z_QHXD1d$R9YKknB{T;=$yTd>J!D5ypBOC4r9dce4>lX zROx-(s;uU#j;#Cwb0MJNm7$Olf~qd(+zWIzB?=+gRLZ2_!E6A?I<-cB4ZV|^peuGR zKo7_oFV7lRH}G4h1nKm0nkVX8kIK6qF)aLM=+}hxeFp10jwbrYstP^!jyIB`_bZ=h zy)@C}18QTA^2re`(3y9$0n1VJ0 zE}z=ReqG3r&j^Ux+rI}7@Jqc07Az&m;44V*7j$)}DOnUGjq-8t>a2gVoMaYEV`nC) zh!BzSO+mcZdhWTQ+i(+7l0>WO%l&qvYjh$>fsG?ICvMlT1K=@mMx>SO4_8J%Xs~kKu=!`+GU4gJ` z6IDK!WPpNgz~7Wd ztxtYf3304tY^`xRZePx>JdRNYs2(JSn~47iR>!erS;jFD-I{L0ad98Iw2nP~l&{5U z9cpR)Wiho>*~@Dho(C`Mg@w=+a`Mw8NVsy9em1@qK5FNSkNoB4nS2t-TBrT7g{Wt6 zA5u`_3I;=vP7~dwn%tHb!FmDrm5u?2m*gyNVXCNLz$O!s&CrKq zW`dDnV<8fe#WoER(!(GKG|M_&8{%E7Jsx$yasTy^ zhqo)eL8gr12LHQnk8hX0k8f8VmmQ9|-|i#IK(b3sP=;?XFy|V)az}v7Hhr{IeJ20FyvCC`tv9|v!(Zfp zyW|gZn7&9O8h?UO$7@}I4+5gk+$F(y1B&;AKa_wx>F>nvDStQtJJO$DdqiF+PYjE{ zCw++er2H`?h9oYLA}>}hR#CyRW}_CPp$w5mQGuKwi6K@`98DZe7)_#xr%0qoh$WV% zAduyWWeZ_TapSYbwdOg20B*3C1JD5?ij#n2W3E!J(sxqo#Wnyx6+~;$6ElE_O0pZ= zi5h?eU;?l%CNEwPJw<@5V$N{uR)^)y@c_V;VAVP}sH9_^N!^R_x3zKZit(x#v|dB| z@+2v1YhvNv5R&CVvp8gJ-Zfg>@kis7B~*)n?_I)^4C%p(1st7cx9GzP&vdzK}9Nv89 zPFz(p+-$$IU_Ks%h?q~GMDqe|m3Gx5)Yh%teS^np+xRI@j`%8m>1~r!u%^i@a5yN?B>gFw@}a!wlD;SnZc9fHsWbOg5 zFyb!+J&?tHmAsSuP{icgxw>z{Y*<%UD>**-Zo*ZopO5MF}7LU z#IUe%=~d(5D>BEkWK6kk2WwoB6;|TkMw>)sOLXlGkZE0{maB-=cX(WzC)~J-UG8v( zm6S}ipq#%Uq|09wPD@$4Ly|S%Sy;F1aw;{ zb8GX@gDAqmpM^&H9%#1Mup@IMmrrh+2Ock5jf%i6`Ch46a<2#jPzmZ<+F4ODVGcl_&3%E?s_xX;OpS?jIe9u8fMx|_fbx)y zP2c9pb%(hBWVNNWI(wXWMjn9I!|in-znbYnck=)P6@e6bb2pS{R`xAE023At=cv;J-*8SId&0mTk%3iN{9!~Sc5Sf73oYtZ zi?4rA7!ygm9V{ZAXJK&YlrDr@{N8+5*}XMnY*9s)UUf>;CZt58()A#ykm_-b#Hp^b z<+`}C={i}*eAimtaTlkBrx=&cy;jF`*B`(B8pV&T7?-+tIWTG}>T*|2;c_jWXHEnz zj1GTzOsWU7wXrkhAc0RMGnwLq&c?9)O) z7>xDp@sy;6Mswtu4g>AQ80JKg=3kJ^iIQBzYn}AI_p&Tnv^x@#mM#-%FH`x_Dp$jm zEs&`1)hm-1_C7Wvag|2PvAqnCrT3p*a|6>mFFxpzeVDOC#645@De?qx3x@l+*x${D ze?$F(Rx`bni}mY~$Fq)NlKp5OJ-mA6lQZ@~gJUHUEs$)7kgkwj2F$hLp5bJ1EOT<0 z+T}HDL|<@v^siow8d#sJk6to8*qGKaKj@g&v3is>bVc`Uui{1b%&%^ZZkwGGnm*$C zHZ`Zk*M0e!`;gM?Ef5uHecoN35<0Wx_zVl!<012Zebo`VXL#iaOg z_Z`3!9d-js+9h`Cr-?F7^+@`MZITEtnXtxCyrnwDJ``yWrKc=zPc(#l5Rwd&fc(Z7 z2Z@|;Xg`FU1d=QjpL_s2z$xIHgvk#B#v54v#3OHySj!0QR2Ba=?7726BfY_E;$+9v zn9A`hAM;s?5a<>5=ywXQ1Kx2ddX_t?G-)kpW(va!0ZXbw3F<*cqWwOt(85O1icP*x zkkQ}p)e|T%`>^wdFDvI`!*5(W)DB&tYjKMEtUiJQQFAyQArw?H;Bu2hlb6{A$rkFPOOpnK z29xDC^hw_MNmq7CUZe2I^{s)n(Qzt*ZfC(OPDA2Je-?)hT5fE9yrvXkT0ZDArUzj9^HbL&#)F8{3nFNJm zLLosFmg|{>)P|@*6_)C$`b`kaAhim2|A1Ipak2JmsnPRVosaF}|2DM>d zgw!f25a_o-LJ4=V&19=asuvb@4ZuXK0p+l=xPMKBP;ZeQL8)0ogiz;xV9_9MRUcUX6ez&iNx^@~Gn*qT9Hg947wRsC_YV{xdMMwrd@bg@T z{7cz>?@#{iIO?XK@+5?LPV^Vw6WnH`N)cjWfz8`6pFAY6c`Gu*x8cqhCW%JPas2H@ z0&t=MHgCL>d}|JZ>&E4@Hw8s1L+WCFiYuL0Prih)9XKI#hw)A(RDTqtCH71cjc?}2 z5L!MeQ0fl*qglELLVG@~t#INFl$=?Y$oxOrU02VnYXRw5VyxZtqJWPco3`SGZ#IPZ zD0GxQ^l*?xhAg1`U|Mp+K!vYrHRs##UDWf$dc z=&);{3p^S}j=5icnZ#P-Fqp1N!bXZ%C!-HN!Bdb+K_X!bmHyep+B{{06Vf_!QX?sa zZc#s5f3!6`Lta(~-w}3;1j;7TozkQ>c_FSeRhxIjPt?X6c2%mmV#zvO{EJ_n=o8n{ z|FL}oCd$8W-~P(K+alZ)-UKEZ{fwIINrqfbPHheu{$3I>I{cTZc=PO3!f*()q@1;! zZ+E|e8uU*;e^4r8$_OeAApf4yKw+9g%<*$ZFUq*gVpV?zr6>1q{5$HVU8l~-fAa5) zf&@C{tWxG(6F2~NAph>)HUQ+`je-1o6OeyD`y2nx1LWVUfc$&o-}v|Hzwqybo-Mt9 z;ooh%ElW13BV?O9u+%J9XW}S7IwD;h9|?jqgAMuEi@E&)&^*+=tq2PqAxpi724fDB zt4cs`Bn;+Z_3>2;u54wjp$`aRQ8B6~BMKfBdWpo^kJn)7G18I~^1^2k0?I{n)O+YD zvo~D;jfkoQ7{WxpBZ;sWHDON>h9I&xA`{#imvI1I@p$Ec4zb`>6LE~(cz(j;oXH4h zeH!&d0~2>-2uR8Zi8rjQ)~KG4LgsGVFylY-?>$wbYuZ3pBy`mOb^FG__ILjMSrc6n z`6JX82}-a`+9KJltGg&s3v=9Ov8GQ5@1RQ7{Yv$1&{ks>)zF!TIb&?se-5egh zDSKC(S}(h2jIj59t9!}X{^+f(sI1NX{?X%t*w3H`Ux*r4&pq~=FH3Tb4>N!WC|H8X z{j*C=m}hY(7hgKp;JqAn6iC&7$M+7Fg|*f_{QD5ZV4$k|l%1mv`UYy-%q>@a=XUqv ztHyo~$o7aY-@Aa~_x?B{mY4APv1kF~Kh#BY*xzQ4;Ux@NULxmLqI-@1&=*}{f15jo zmJnolnFxc2Tf|&gya+AFj5=Y4=9MDF1y7M}t{!(rIs{yk9MVd`aSxrf0i0ea;ptH-pm_v6jN!#3Q<5 z;~jAV&Q_JhEax9yhfuB^J1Bb;SU|9YqoJv_w+@U2iG@kN)kAY zFdfNeSbDxn?xEdqX5f}zq!SN}sv`xfdFQ>FKL&+HA!L##DT9|Ef#t)iL6F}|ka-9; zn8F|mtajP#&l=jrpUiE+N73yU3cqq$=@v<{WyuH$OIkGm!j+URtUc}3wMWIXI4PE} zQ~(jG7Hc&@Jlxuc_mdfpglGtrl$g=&5mmp=E$IrroP0rx!vmkK4?I`G36W=?PA|%M z_hFr&DVNoR#JMU=htmj|1gOjWl*-0~jDcSui%avZ$GklCen}RF^kl3R19htw&AG6L zOP%ATM4jK}EPUk6rW#9Bo`Frd`7!QJm(Yf{LK(?oSbN1b&8mhPg|+!6qP(viTVkYY zarRuT5|2?0UxEnb$)ls?%3DF&+t(>b(*>6T^}Ln}d!vDCTfczYRsle`6n?%W+E}&3 zK(sP*O_#^ZDzf8I@6_;oy>5zhcq=qAmGG@N9;u^I*ei^b&1c!jMyYXwcEr&%Hj)^@ zc`G$R@2je3IvdK4oO%)!r-f3pI=JyeYJy`mj!h{g?pWxdQq zQ1H@HZKOO>nZ3wHf<4*>dx@peTy3m8b{%X#Nmgx=FIr{wEb!%zB&E4OzBY6CiLs)D*DnHMI_le_dU z)CC}(XjH4BT=2dp8MC?RJB(vA+!|9260t2V)k*uH+{;tUB%_DL@-fkNX#7h6LT$F+ zDVo#59b^x76nN-OBjY1Fo03)~U2xDLanU+X;cQxG^=TR!mCHT=8foC#zSk0stTYXe zN)2jjd%2>eSW=a<@-z*FN{#U5Nq~*JREq4vFjw`b1E(=t?Bw5@pB~DE%&KPWxVo|g)e|GVZk8#Iu*uC>bz5U zPxv;BTw#ycF(N-~cpHzb9ZKj4T|qXYhQvU~qu^5nu7xKelYT#OXeGIL`6t~NlM}`V z;iQ`X>Gr*}HXIoko={&kVdq1!nwC$3tYbmxBpc;(0wv?T$;YV3$^vNa@_Qp#9f6@BI;y$NS^xHIa6y8=0dgIl%6 zPNsyA7&WE+L_P2KO<*Dym2?Ad;&Urk*|49xRwKBA6{o zt9zwPua<~Rw_CQ)r1dEc)P1s@x4WFNPPAo1&M1ip zP+DBrG4(#g)F&zQ~_X<$J_~NA=jw9tprta-&phb z%N0ekwp|&sqC!Wihd!A;Ydnr9y^757P_Si2zIhWt*^tuIJQa#@_UVMttRxBim`cVq znaXeN{TsreY*ZqW6r5UYc`P5tD)e|KIhN|Ti~*&KT)Z2J zhv~1Jc+B{3bKa?5bgz+F4HOr5l=I4EMIDo<4k|O(wFt#GueI+k61r|4PT8^UbOzEJ zVPEG28!gH`8P&6kGt}N!1`z-ThyoTkxaL1wJ&HnkFtItN+~*~Ob|?CL&9z=PuF8Dd zmBGUGJI4vn_W`mD!u$o=f4xBH1$mW2g9eQ;$gMVw9bGRD*y9toAi&B(QY!Gte?gqx z$bnZAkO#$d?Vl_z2U%THe=(WUA9VTQqjl`G36y{=$&zHln(lH(v}>GimQ)}5ZtxoZ zQlM?O8=ysRFCN#>AJZXp{AH2bl1$rS6L!9CnfkCfRH^$8`OkSGIPg|w4a}2S;NZ{y zI#2$AK=oz8gwgqns;V|pEp`l5z7{~)iy;XE%{gI~We;CFV|f~8CogIK)WJpOhxrQ$ z(sc6DJt6xeO!u&Q&hkG_AAY>~e*xw#;-Qf_%!9t zh>@M)dnpK0_0b4G^tl}V7wN|pZ{97jNs3kjP0HM}a)n#pUEmZ`wJBYtkB`BNcV}6h z=jZd|Tp!5!u%ooyfH|fqogC&qT{XmBeNuXV5;NBuUA@b!D-s8880c=2J$BK2C~20y9dS`Z*O$pUN~&8>K_9@i3&7Y-wL2F~Z9)PKl#sbSkJa)5YkIhS`7W^0&`NV>*J3F*Ct!Qx8E{jx z1acZS`7hv5Ym2lYRbAa7gge~j($iYY~eF_*#` zmh_L;4%H*H$qKW%_jVZvB(9huEqJ@v8J~?SC zPI|dn0S>1%v#&JjDVBV-y9!Ij*ge^{><_5v`0IEtrU`orGk|U;a2(3@DuMDdlV$v$ zVCCpsf!?3DppCVrTHc`L8Q8+_1R3MR{o(+bxWjxORURE_ox>gB4wnp7^8V$yEYY?5H`(`wIL(I3rW4&72V zk!4pJR2!mc&rDfBLaPd_4LK!Rju6rBcz^mqyICT ziWH6`nX)jj<6+)z#~G6Lx7ZS=oA#Wu7V}E#M07E(7erw#y$t(`e=8!E^lPx>ULuOXb^_}mVL@s>S6m3__7JX|#YLeg zqQx~pI`YmUR%_%-bHnOXVbX{{<`xa^PwXK{nlHPikoU%X7306qFnXTUMl7HBLK)Tk zBI>Aijep+ruHLNB%>To<9SmF^ z338DOI${lkUDCRT+PlWPNiFwuJdA4ZIOZ5Fqv0o;ZaE8@Sjw&f@>EWH+ zjq?uHiH0$5TuZ{MjD>5#6RUJx%$20S3spB%c;G4vu5p0bW0_^~HEB1dlbO~)Lr?Gs z>weZ3Z;4;M^@*#ZAIcAZNW8^qpVHjaVG39ISa_jJipjHb;mRezwuA~;P69rQLz&jcj4#y>%R#8Tj*5dn>0C%No#Q62j!c$;{Ae^0M% zJwN&RLOX@)!8uP?#nDG#6qZE{xoB@t_~=fqw{I;`w^`N$+g$`HL zhkPHcSH}KAzl>enxbO?%q_Y0my-xM$vPQX$DzS#A)OZO&6XKPM>e+sm*($AdW~*+V&j}T)0&BY9sZa=wK*FTLfKG*jI2YYMcO)`7G1xgvF1z<|t*No1L4- zmp^1TA`PMZr-%{j!R9Oj`qmgl6<=XP)m8->m`MutSb7U9Qp4Ji@`6%s{qa4t!q>ZYAJPg;wuSgv@AWDBj_9bX9wVqIo|( z26aZpU|{52eR&~9TgkItCOM=hIvxCQop$SC9IP1Hg!qru;v{Cs*cq)>?lxsD_AN+L zc16Xh=p>HYs8HL9qn|i;uBnvy4DF#8hls%1(oDUrJt9KU16&c&RgDvc0$v ztIP6HRCsa{Wsyk@9wd6v1u3EJFyju#iMYb5&5%=0CDdnrP%~yBkymdw^i3_2AV-^% z1CifxRr}lI!wjANgw9V`YB~c|wIb|64GO|w84Q=y3wZpxK*pc-&q&cik}-C;s=W#R zOt$FY8Edd$l75yv?1G$^oui~b=4F&C)n#V695f6c@pTy~oBS5F^(n*EyuZ)T%(uW{ z&t&K}N_&t?J=dCBmVh;y!MGIi6nROL{U{AU=j_XB)LK8w+#AOL3Ia*50`0)Kdu5 z4Kts7+G2dukw0RkfEJ!yb6WWAE<2l9bm*B@(u%t+meoIkYeTIy?}YWp=J&%F?$Va2 zzLJ=pA1i*|$V6V0u@TM%m+r)14E%>I^vW!bfkK}!TJoGNRex$UKBPDz(k{(4+tX@1 zjHB(bXkVytH?7n2{U|Y|^2{Kd+wy8|wl-nTz|W(_C`lPJ|*KhKO{DczD8k#l2mU4%Bt# zoiVY1CeT9g&KyTsNy-g|CLicSGeELQ{+#HBIr~Ez!Ju(f`iNb~IA5B7L{75j>2h?l z>(U;DQj5|d+NhD&Ln6!|pZ}s-|H?Jaw8ut&+jrFQhzcq&1seEG$#~pedcmbVtR>vWI zJ)^_@fcobKXlAL(3Jb`-3nKkb1IPb(SN^^KInzWp$NrpYJU?du#|4W33q-wi(REaV z3pApp3T%O?(8u?H#@4g2^7zWsm0@0yvei_je;-7IIyW%s%Hw}|bu9W_bgc0x0|#rB zVEMlJ==@dSig)htQP1+@>9K7G)NUx{s|+)V2^$R3=uAgyB4OUD$8z;hk(Pi;!H#gW_HOqO)~*6+kc^^bt+p}^y$-J=+lwN5yv{K5 z+j4P<77xrpi^MGJlZMW#xQcpsgr$NF@f|y~=1z=nnV0&!=9)-K_G}}hjHdNbmp{qM z#MX!g_2v@h9O?0qQ$UyuowPgx*v3{A|0&SpBRPa@y-^s7w}eba0o%fkiKcX?PwcdG z9E0JOhJi6xo|a2+$Vv*nHP^L`=$aiYryh$Xil?MMP*Wk9O(Ivl%4Fx3+E#k9!m?(* zcQB{m=TTlzYEj+*jS{T18G{UF-6h9}R21Pa7$&72UB1o-iK~DwpNh%bmtla@lB7zN zegt7gHccpyJ6@P1rng?lu^#6(+a*0v6p4tV302nzgGl+{H_NG9F3voh@kYmI{u2?@ zDC`A^KYiI&IWby2vymCG)5GGI6niQ6<4{fY0XsRR_M%|g?$CzEF`6B{tAw{7DjN(o zEY{<&lI8nq>W!21^SYWm`^JP)IDCPXk8}~-Y8H+><(LO0qb?W@0b?{w`DCqJKp%ao z69{DCX*orfD%8?U`^9H+1qF%5+@DJ6Ci)c}8^@W{R;x(2N)GI$vgq_i$-_u`ndkXw zWU}S}o<6RoD02Lf1=Q_=T<((oK5EAwEo{Yj5B?%RK}iKOe| zWlXE*YU)i`ZYP4%%6~U?_T>pzeeTVcC(G>Lw)79#hn5&{pl)? zO~<89!3RxwOkXXWL~F^@X<3{xC+w3RG#QEd;$0LuQO#fLc-BoOxP^V{44(_%H|MVp zgZ(B*%BO4VdB7IYWF6lAW!(;y{V_A2&4aelIX|>_-$r-_juDIx|M-rz|K02&W_H`` zB4l_a8m1=ec(_Z**Z-X_I4|Pbh_y!GtPx$;D#Z@Uu7ptsS^jPYrB`UvU_Hxm(De!G z)<-(xQE0zz9LoviQ0xg}GjMg~CmYfyADC#`)!SOX#w{JKc`?SHmeVrEB^x#5a~ZI% z*+w0Cz9onk6h0aBHK+4e<*^o`wNn@L%6 z>Wb2ht^qCiflj<=+%bIBxLs#TY{=_PiC&BdcDEL2Ujnijg~T3LDw)SZ^8~EzWUQ@Y zXS2F^;aL?|{sR4mra@QOXK&4kl9X*P-*1O}gkLp1yv}GRd+w+R_p;PQx2vermR0S9 znD3R%;HWr4f~$h#)e~ZP8Uf+&n1S}KDaocYtCF)SQ>xrol8nX-#C2bgQzRQ{=Oq<; zQa299?9l<}MOd4{(C$%5U0}SP8DgQJfbSpws@?#S<^R}%1YGL)-?ku`JGk4s{84QL>Lbvd{rRDZE8if`NAey|%KENdU_WVBQqBz?j>;L)u4ByW) zY0Wnr3I*zBg20Vv-*B%XO47=~UTkuf6Pmla4qzhG-N0=%IqM0%YG@f6XBA+Ai`E|{ zG|hAF=Q2abk(5qOeN!B};G!a6v# z-*Lfzd{8ZsBQmNx9VeYaDyEF5>3~$6bW{=Aao?;wY~Hjp@NdXeP->{FBe+f4T<;~O zbtWN@{HpKfNDD|K9AokIc;DNWRiU}e-D}4U4kT~8=gvX<+*FWhUU#c5XIt)8+??I_t#)yY1^-Ncvm4MPqBtCf*SyShWO6sv{Bww6+U z&C1}}LOFM(MANDI1xh}%in~(%W!T<_UAsP~eCfS%N%m|Ma08*}&Npb9!;rx=kZvZ& zT#CaQtv!lwn%mH?Wk$!GibET%9y*~lWcuUg6Os1kP*8g8QhCRo+F=q*E8$Is65}Rh2}@=jj}Bc^8sA9yyl)RCl1h3V z6&aaxiz~m+@$ozMZM{GIe7!T=c?U59$>ZF|cUW0qB~-E<)LxC2dEa@7%P9gg5(9NO zI3;Pr?9e*66su)+F*sN!Ig-3IIslVMX&}5;mGJPib-?P1$&6~)sP6Fbc(kegv9-aD zW%>AJUw`!5sBbiMH2tXPDCwx_=xa0*HW7<}iQlx>;1gM_;{MaLkZ-HaMwaz%d#pO9 z$Gi@QQ8b=arhB#f$@3sbz3-8?%2OL+^Yl2c`cx9m2{gGdxXzvJk3*ip?Gx$a_yn7J zldsyoL~CNBg?g>Np8lmq`OaoX4d%sq9#slT$v<+XpJYEX&pTqNusr$FYUMrYRuf$y z07Zw&X|sCkPNOW%V5b=_O}WXBW`Fz_J+OlH&mypbuNHDE1WZ#R^_s=L-Vv%-&{Yu5 zXiv4?Z9~ipRa0r}+{wxUWPKA!?$^sUacu2pQgL+bGFA+b4UAyBzH-n43S!M>E42pP z)K@j?rK13hg}cr)fecvuOD^-q#rD+Qmc0?%%c(g^S2hgVx0N4FIvfbPu^8Fx^;KP# zvCBCgSl(CMQwgd|lYxI^^jN`tT^PQ>xDGb0p3Q32n><6s9!@%tA68VTny(~LpQzFL zS02EQVVMgYRMV%19jk>+wdU4!9BcG678fd$+zA%+RGH|L5!c5L>tajq@sZAqGchnV zMk|ksk7AozV3VZW?WxZ4QS2 zApNwx`vZHMtJ3O}s`?zF&g0uH_vv!9$UZ;ZrIrTpuCcDcsljTtXo_er=CSi%V+qbLHQGuGZ3plul#UGWo4^2jKMN7;~|6MN@4m1pCF zo3|>Y78?{}5sQjgM!ukU2xgM+MlKv0?nTbo;QQLp5`$@Tu_$Llu*lO^NT)wT{E+2E zJq(HlEsD?L%r%UHCMoKcbqsq`8L?07vt&ojuA7%xV>sg>G811I{cZ83BIjp@p(ZKR zVtA6xFg1p6qKSes-cM)8^7aLq%jifvHC}8LUTh6h1=Tkko1n$ea>TO+M*(#~Cp|#e z8=82Cy->EydU%hNksv?8po3cxWRF#e;VcJ2VUB_eV~z%NiXV|(Hw;qFsu0%YLiiY0 z0A=zS{7Y$H@x0+KQ}2MXU!3Vv0?T_a;alMT6Gq)G=j01-&JEG=P~LG_iq>hk=D*t8 z{?}5A^>2!%g|)ez*?+IKRL(b#m%xu30cp;E_on)fuL+x)I=VZ!NsCGR<JLM8EW*PI zg!saJw9VMD88_GF2~vh_9$uef5^s`jk`Z(bHvLNwPkggIUY5?E$DR z%=7k5QNlmdx&BE&e)zoqYP`xkIC-kPnF?QnJ9tTSoKg*repN8W`)k*mcsNYZOnxom z*N=}I+T##L{^|w_;^_L>%(s)!+@+c2WTX z31QAan6VqjD2g4{IM{yqtqTOl11vYJa_e6-eo|NV9!J1%DFegx?-1R8giFNE(d54d zOKA!iEaYr^V63cUzXy!La{YqmM23#9BqZT#KHYLgYi%6tzA=%Iq6NG8`FBHv#F~YyM7xQFTc4?%g|FG&};)U_Puzt@k_xIIsswk_bI%u0&ke6lX4JW+!zIg zuJqjM$I>B~2L((&Ooc*&kmrKVuJQgEI&@J%;QeJ<^$-Yv$^PH}$A1me-$f=NDu3NG z!hflm8Q;JJmHbUvtF<*CJRO@aAl}GMrNzVdSdH-EpwnXJdT&xX3^;#?kqZh-9Q*+O zq#S;R-asjVzT-RFvohA(`u*d@ALRj->u$kqLH2UivxH2Og-Vl z_DBY{`!g5%3mMyuS2dY1=@4gw+7KI`mtZPF$PkC`f>)m-(VGPlmL{%#V)g>v|v| zhGLvDWqM$*eJQdIQ#K$FFuUH6CYedyv!+oE{iWye-HA?owB9WNVrWkgu)tcK?ZVzL zcyDo5?<#zv%CnXxgM^*>sruWBH5#q<7QO(_#So@|QhM26yj@Xu*~0YBS*fh-7hu6i zcqTVT9Q}q_^n;}Vi3$}g*AJZcb@!X_Zqs{|p)$?IcQI?uGK|7Q*Hh%0gFk5Up3I6! zRnfQ_Cl-@dM&MZoQR(Enktvq8FfdqFdJ~d|EkWFFpSU!=nOM{NxX-AyNi_@Cx96~;=Kh>qzu{>ADMBl{HgJAy2W+7@!vnyp8 z_!JghA)%4@?Np)6MKXJ8l6(>pn#gu&8X7L8-A3h2->aU-Z8Qx3IoHdM0;80xvq#C? zNB%t4E7x3Bhg`n;M+1=KI>!4z*{uBqg+&FHW;#*cwXwZ*J)+1mY#pE>sN8Bgiv!aK_hD<`ynPtgLfjsGJ(jOCD^*_mlrMBaXi4~;w zC>bvZ_6;7mmasIP!M6&O-qe=Vdn~gyRF>T2v%jiSy(laje>8FFie=DJIdfRv52s|) zQ{)bx*v=uPqJha&?7z z(ORw~HaQdxUu4%%I{ZH8*(1o-SL{w|!VC9wZvD|7(u5bG%iR@WC@$BWZ4E8@|~1KOF$(i8RS@SI`qTedy%_S~Ar z9(cC)Ff{jugkN~m#c&vRQjWmjn!;XD_Jlvtz8&X{^Xvn1-Y+}G8|m3g3W1R|ezx&4 z>Kg>h*YG(P55^nr*-KJ^xwZFUEH2-GClX5}RKvY<;=QSCemTF8Cdu$Rmj|jF_E|#G z-r2SNVNNdJz$XezMbw?WbL!JKdztQ`4E*7)Y<^L{xF*YpE7u478}Qj&O8@aS_~AG% z--IV-OGXsI-E;H3vg{s_x9BF#h&7QR@~%SuGiFZ=LZ7iqjTSLIZx%mnKdLa zBuhb5#94n5msx)bAMV$XkNnY0C6fL%|H5DAiYD<*ec|%l zuUT;HMPjbAUyya3JmOaqZH4Sc*d;=AR0|PT*kqbZ#CU5@hUsc2nA?srvsieQ3Q1S^ zl8?nAX7yO9=0i}&uzgzNW|q1*AbnK#4Wu3vZ#2xZ?x$lx&-)q z&l3rJUZzKw;I%J=Yh*4i%3wZ7HxS&KAxermJH^3u#a*?5*xy7b~Gdi6j@@ zRU;#8!uW1ojH;V!EkScshTR@jSRivgr;A%B9X!*hL=J9XldEGoI;h3NMQ*$-vBy5q zDBh4b31PuxW%B4!9^dvAS25E(f#%dnhRS$U1u+@nlnJ$}S+#did?`UJd^E^3p{R-p zZ9#;3G7BeCVn)r{jG3HbB|&hHof+ReslkE;BVxkFB|Kx_`AOCGx<&PVWK|^z>STgl zYse6_&Ne>Jn~J)r2l3Vqk(EV8wV?8J(2NVEZm631M$6kjg&(GfjF5(r#n~<+iIxVJ zCtq8cEJ2RoB(;>h;Cp1@Krs5)(3q@{u#h?b9$f^xnABi~ylRA2Y zc;cP932K!j%yb^ya^%&2DUNFD;q$MR2liuj?K0M{f6gBEW@!A{| zqI&0)VLKI{AbJ(sg|&p>@|rl;Oy)bb71L1b9(BJ3>7tdfIu$Abk<9EEY{Pp6sz>!& zL}-EoEza{U(@b{Gq#g3a?fZG^BEH#rfhHK&BfQj3um&_t;*7_73^x&sja=pJVGG#VK-@Pa6O04=fdU}3yWXpoGBJm)0lHyU=5j6}zrFqHf zDBZBVt6V35wk*VEr#f#gOEU*X90z{U~}+~+OZ z6}lEw3Tg7mOEVGrirIMdBfMS#xAvjDM^JO7B@I4uK(^L5{;L3( zHwhC@R*Z(m(5>pR?3ejMAN{%RNi6W3-gij)t z2R}V}eb>nC3{3#LB%vBfokYh%P35LB0xi*RX#s2)=D+8#;cdCY0YF;hk{tL2Xb+TU? zh-J(EW5c1O7F}mt6qQh#!Wb8ELRxl0F+GhkW^!=SH?GH74M4We-k90;m|rE~5wzLCZ-JZ?9__YtpgCxL}9>_6C6 z1IPTAN-=+l9cAE(P@ma#AcdyJo0T1=hSp7YkXgdkC61!PJRdS%iIN9-SJ>@jzs|a%j)POZtgw?hhW?O>qCyaEJQ8DkYXTCS=N(rNd}roIM^JC zGenz_Zub`_zy+`Iew{CS3Y|_5LuD*5-^>7tSEg;|rE0y`Wx{K{xr#;TsRN!6)uZ~a zc_ktZr@LcM$Y|cDjAjkMn3egUEhQ@*Z-*`1o5{p3(WGoB*(|(IJQ~!7NLZc9NG21Bin$PAl_n|S zjYt(*JOk^aU+`9YOZ8kzu6A}x(!OBhwMjxR-6KD^8j2gZc=&#!vh!(^?Z zQ&za+QM_Ks77#*&;>n(Omm~73#Cao1K3EbteS)cbFDK|;RKxQZKJ}A0Iv$^{hMfs| zZnRx>`Jy?A>8jGrtVx?=Jp6pe-#Jnp-H-X~g2T14e>J$h6um_H$W-N8DjlkGWBSEw zQidd6@>^xA4zx*MHB&C3S7m@?tsX6Agb5 z)Q3&98Y;)LMNd2#(%{zzO#~X!d=3bl7&KgrZ4H#a;MNw%U`1??mAW=+L1GV{$}zew zWDK2JX-LJeHex|q?>`~U&^~fTQXf2_&EOp08qD4noOK`DnmplYctLstkP1G^DR`*I z5FO*1FkxVbOL_y6N@}`2SK3)j_QaU_eS}lukd0v~-qm*^+)$hFh9OmDq(l6WiJ>~) z)qf&={usvWmRh_^>JW$FGR`%6;>C~~|AqiHODvElZ-3a3o8X2#b!x;z`Vg8yC+;b1 zV#%4akj2(L`=z&+&<%+bo#?=^o)8$)uDFuG_Eacs?1herhTg6QyKgN#rSYb!8Vy z#7Cu6@gk&LvzLoB7?<1l051mps_CM~JB8br+^L&WJsg&#MRlz1MeS4FV-ibnRIg6? z?8_yhXQ1vbSuC?-xo+*kVUzRWH@8MF3jf7m=8#vzS;^@ng%r_g%kuQ~D)!VCCMOD( z{+XCJYr$eshDEN0Qg*%7HM+(mR*T}?$ppUOk5!QRm+f{O*L4Py2Rv}ptgRgr&LE2@ zQgtGg89-Qg`KRcWnjsq1;OO`&Gqyp8F2?aMb9*E0z*$_mcAT&3`>*u^>{ps%PrW(g z@QrB8(gu6KW|iE)HlFw8f{OLWhpI3cgC_c|CRjlu@77fDhHjVpR6C-$?TYq@bEbIj zrmL&nFqZM4XOcy-yZjdvwg6Sfm`E_QMYeM9!OLHp^BN|slDX%`_R0ObiiI=MJi&JP ztfrHt$U9q{gI?!=*KSV4xbA2#D2lxK%&(SVc5WAsNW)JgXx382pMIb+(LVvsw^K#6 z3Q+`BFLl(Oa%qE{MFTrzTUeO%E?5k_DGOBhXCQnf8u?y*^_89(}Vw z-QGYG2Q@XU_G2h{q{)CgU7vd`>dAuRu#wFr4C`8u%`=|E{BZhO27OsJjs_5>?Qr60 zY10VSvE3@(J_Y`2GgtGQKM>~9El*g%hM*8;=K7Z)?bD^x+d(hOI_86#aH+4#SUM*6 zG_mM>&%t?w1@DC8CF}_dx5SSW#Mh5~m=Q0_r>N+ZSw$^^*A9b)VdE&tlv%khMZ0QYlqgfmnx!sLyA*@=s4A3M#V%dDpkd}H zw2B>~ww1esVW%jxavh4-41?pS)v_J(*A#>0sMT^E%C?=mj$uobn>j6f*TRG8DAvmB zB`sptXoDK4)(Rb3w)ML>Va^nrg)Kt1<#~lIQnu~8aD$m)?I_Na7jo<6F3r1KVJ|3` zN*yxSUW4E$c#0mP*Ls5@D0oU9lGnC_q$t^n9^%)ggWplIl{}=cT?f%obQC?ru8js& zP;`_$q^=zYSx~kVJtVFz2c1#2lssgvJqO`YcobhnuMGxePdTfqzk}o5zd&X9l*9b(bWj}Y) zlt=C9zGn|$e{~Ul$F5%nP4^Sn1Fa@AX9NBjZN-?h0XOw%=+`4+)z|~LR9RP1)%wPE z7oMhu;S21T`EbtNT494lCFN|nqeOEJjJ<;)$>Kx8XJ$cAdDcGsXP7@=n?(h25dbd# z3t1VwKRT{2jEf|57BtPgV1v#nLszw-Jg4!ci=c_j zX~RR36h6QB33F#Mg8-_n`*-xbQ=ykN)PHc4kXVyG2og1jl|Y)?Dpd zR}zapI>9Le@6*OEb)Jk_rfI3uXo8bjuo8fp8?ar;8L9@LDZu05lw4S|%)~pEM;J@G zHFz9biXamKC5P>S<=mKdoHR>r!iFwu1a&LR6zq86kMf+tvCCaDla4uicjI%v!`3RC zX+OzvO;7NKF(Zx~N2?c{X{u(}FiX4IaOSn#N`&xL+AY9yJ9_;3k}GKwZ(_z=!(g0g zTV$KE6B)YU$`N9LDY%2!C>ZCVUKa9t|wfYAuP zFLMXm9HYzGRbVnQL^F|1%uq{>5^ZImCaSRO7*#>cX_`sV_LWJ$Ff^q>S5*&c_{{i> z)u+jw;T;yYv(4i^H?@z?Lp2h%4h@^`VO_hW6H&fkU9;zRw_}#B{|X^D$eS4(W>Ifl zh)qmqQg`LgPt?FxYc(QD^t@HcEW=igIxXze<#JGx;RC~>lcxh%5{SVE?QewSnP4u? z@3|8FrMtR8DL zRWH?QRYOhccO+onf~``MYCmoR9X|6rvz%6f+R#iRa!BTnS~KEpTDZNDx+93ljV34)BAoDL^P<0V%TSXv;MdgmIVv!W@ z7YY(p!6qn-?W668ViXt87b?19lkZ9x3LzovkA*5=R0avyiiIjv{2DOgP+%*MN$Zyv zN`xwL;xeNMA(Dn)h%_S!f@7MOKoWYGS4t$6G>bCB&uCvzDxXH89(EX|NKwczBi>+B za3Y^ZpdOwS#i$@o8p52HNHiHYYcZqT;8egS&o0-1Y>9pHl{}NGPEbQ6jj~Wd(0%4d zEWdmjDSHT&2$V#rrUS}3&S-*s;PF>>R{6q&!|)$@`9wkm4ZIGBnb@Ye33C9@J2WQBvx{Jp z&fY1DooLR86i`+r&AR5%g4R=K(iTDs@<17Ds1p@J3wdKd3dyTcCWa3JC@zW}AeCxT zfVJTqFqCT2fVpBHK$U8egJDJ4B`Q{-3AE&E5+#}s%EneTX^Ss~>Je&Px{+_-2ZcKf z!pgVFMdYZ|7N!?C)MJQ24<|8;o5o`ZeO_3_&Q|I(Qe$hhNr^Xyd#JNEHK>U@htN0J zSe!_cZxBP7>@3fskz1k~nC>jc5f@tK#h^t|TPDxK$q9bm?j&xSjDc=AG2UO!A!#Y0?NCcJdtMZ-;4d@9ToMWE?6BOwdDkP*G<)-ORD#pw4% zT!J>*oGFdP2`YIfg|R5@@~XMKyVe8@!^X^J%xd~B$nAuNysHMqWr&)Uh^q?4W#|g7 zh^r0-UI<%Iz6V)i^gt+~*0BM(C!sXbiF~&B$v0bur`{y)Go{r1A3w|{#!i9va$-%|VM!c`yl7-T1%ntDP$2w@(g_1dc zZKie=OcY&Ww1^B(5mmWcO_LcAYO@Ned=hFL*H4u<)0Y6WEnABXpavD{+Y^Z@=O7yCr~!^8lS!-C8XWWx$vIAO^U`pAg)g#0p5^8z zRGQu!5~ki`)R}?d2g|c+Eu3zNKl(stiXG4@v%MhZ!SH3V19~=$Ab^|`^dQ!Sgz;^T zFamov2=RP51OW+k`3Qhmf^8wz5yB8#ASHRXdzle^gI5eeaCH?BT}%=QuX56&diqUC zfUNE65nSBU{d=(1#2`8fCxx~rsRDY|R55&6=#YJztHePz8wepfw5SEQBg>$Cn@d=M ztfh+yubL7Bw_!`cVh#9k@`6F{LNuY1@ZHpFP;4te#}Qr8GD44ydZ7fZp_K`v>UB}` zqCv|MJ*ipoW~Tg@Lf+9TgkWm6kp_67X#`;EwxI@ep{w{|YPT^5WT6*{g4Ard^jko& z5QwN+An9lQB17cR*8MOndo4pepqYt=RBcG}dioBqH+4A81@>3jG}S+rs(%7gp{Ij`llH8+K0$PYx5?k zT_NeWfmY)it6pL17lB&iOV?~$4p2dF3QaU^dk$bja|>pe^bUu_Q$3>C)`4ad9jadu z@1j6=2?tO;qR~(JT_Wm1dkH3JTz%_n*j5n?1nnlGpk9tnvF_ap2>}I1gr*uofTk`Y z%0sg!Dx)&S*GIb{+(jGbRn(|}+*J&R6ztQNLKF*U5-FfsM3OV8T?|nVZxotWqk^s- z(Z@l!Lpu#nwWy^DnWIXIRMoGw3Ynu`1g@Re=RzE(N>T}7O48eT;lA2c z#gVzO++=0&&c+3s3@7T_nI>MHbAsdIPN=s=T3w%ebeMTyI@L=Ufm<&+McM$pXGx4I z5#4|;5aFNbePo`%5yC77r_lnw?<6Qcbp&F)0ESvYBAgw4^;NuCH<{o_T8srk%b`eG zlll#p*i&{_Ar!RSb<<8w$s9YujjHhU+SXvdtyk(5wUbWRMf$g|E^_K97vv#xm3 zOgQSm7Pnmb#JqT=9C<N6b@RMpP_D#j91HLD0P8cMVYvgODy zJ@c=RIMNHeM$E8$g`#YQ|FMIki+TxN?n;m`CF2AA$gkR;+!yFUtvO&F)aU`PIg#z_ z_zK(-@Bx(U)@hU4%%!<=4y@uj+{d(;YE$V9Sn)s;c-nEg?RH6RP2j z-s#;ZtOLOO6y>Yo;lIPI1G#>|0m}R$Zxd{dx_;0O*7V%ubKs8A^rRh((^aka9jvD+ z;&2--LjQu7-W-q2AQK3+!agU;5t7Pa803eZ7I3;+bdPcp)^e1qyIOV+aE0}@?IP_J z_9>oAA}mzLC>S`mkpR$Ejh?U0@>LI>MZolmD57q@pa!#~gFfgFon>FBl&>GLbHLub z-zy`s0^lkeP9FE6Jc4Hgy=}~WW%Npz1x~>cT#&;W?$y!gj%Y0sSrp#NlVOK^d&Izw zBi=ycVW_QnFuMI;0B%_t_`V+LQ@n|sL#|SduAC_vDom>~RXX+F2|b&-aW%}euXG-7 z@GaTj;<{b@t6512l0ql&^YwMr=MV9}e~m4wXa5g&5RNSgGv&SIxJ)2|vFK#kc*}JjFN07{yv{)j%d9U==BPSpPDeZl0mO_4M=qSN}9@{BP^}jQ?V~`urRw^bD;3@L7I)r-11{y;J9s z-yN{er=UYZa%f<}!u@6=Wi?^iWZR|+W{L{p<5Hist3c4Xec*{Zk+oV7zuJtjwd&Ye zb9Zm@0BGu`5cFw>{r0y260|ZWnhpgVKN^aMSg%VWy9JisZn&wLeUM3vkJi|Tua@2x z-SOzHPe@6zQY2_VSu0bP2ij?eljfgSpf%TJW$Q$cRJIcu!dsmuW~C(IymE7DjG+H9 zxI9LWL%by+C@W9xc4?X{e0r(CfKl*r`seJ|UQq|avkm?jr!G#gjuTmMEdCg$Ceysp z@%yEFZe$zV|7A@|L8YJ0e~TD1-G4$X!p|Y!fd~cNpC;krn`s02Nr7QeS2AU9ApEv~ z*rg!46$m7@o%BWWdiqrL13W-7hH*$ua$a&?wmz?Dm6TB$Jpns+D$*_%%UpoA9))MK zcG4=(*r(f!>eFpT(P{ej={B=hK#qbsNa{;p7&FVwSlS&m;V2)htT;l?zY#mFf>`m_ za4#e+G6L_0pF;a3ba?z}o_gP7;O{05NL;9Ip+#3`3V7@81sDWBzPep!_6EJ)JyKP0 zB6P`de+F|qkOJ4J5Q8AHs6X5S9jQUS;#54h`j;95ceHl@FA@99AO9!BU_zY!-ynwm z{~=;W$@%~PAVziucllo+CadRQqG0ro?!5oCD<_6BcZJDlz)&eRzR#K{%!-W`{H?@7 zo%5hsej6G|A0#d&|G4w)BcQ)7kJFFPPtX$@CKu7~gvDTIPe7bBrknTWFhq83RG6LP z8CtS^QIQtoh~IR0Czb5)YY4~}Z%w>1?rc&gJ8E=cT>YV8OWUts)?Z+c9-#k|S^FgP zWO?SYzrN5TiTHU0BKV^vg6<4L&*&M+X|Ig=`f+C-tou2D|sy7xCdygI!BS_VE{dj2S#C~qjh{C1WU za}f|TCo35UTWx_Pw@?Zv?UQBmUL=1#$6Eh#j&Y`@*~pVMBW+eJDMKH0pur2T2~ii- zV_hDMw>YWrdzdemwpJzYCzkh})D9Y%YeNG4XN6=(@#rr?E zJrBeSi$+vSV#9qwSc zF%DYs^z`_Pv2pJcFn<)%fc-_qqEv*u@p4dtE_;bT#zy!x$I>^=zZx5%e;XSIT3qRw zcJgGcs5@3H{$gy5Xc||aIE+3JFE?JD#o}kS*Qmao4+!lp+e`FF{0-UB#}^Td2DDGe zsP5T!ZsCtQEBwj11%mNSgt($OE#O#Oj1_b_rPuX$ASCIm zp(GisAyHCbeeEYKeaVX`=_W0pGQM9xOwes1rx>{bp{G#$vKeb^6V?;aO?6Pq8g3%0 z>UPoAjC4@e47~E{ratBNK;7h%aWf-mIa{|*a#Z>5*j2V>-ehEE24$8rad9~J*J9l% zTb*A-aT(w@%sW^DUzbnbGfi2oSgr9IcJ4RbfO4^NRDlOVGIUuqHvQUDaAV{iRT?}u z4qggG!<>W#uGOy`3Z0Du)T^qrT5m9C#9~?s%lf{-gkaq4P5mqI8)KVsW3yy>nLa9o zmD^a$_sRP8BqehWDRwcLl`8Ai&APSw5hCqcOzDlE(x4e_fcb*lB9w!_p6g6?_n+MZGigez&sy#me%uG0SE^ybjtM4?{)7d7l6)$1TpMGea{l(c ziEDTxW0ZTCS<7m%LU`~Ow$oe^!P07z>xH*d!{@te$5nf|n;%E}IdpP~S&0cj8} zJ_GYBSKb4z`&Uym48m%?TU|j{*ja22<#|_^+cY~@t;(|5_{|>2&Tj13Y;4>YxEbsB z`o{kDCbUH-AnV=Ai`^dbv0o?NA766K)IkpN!9zAgG)J>!c}oN2J9l#A#R{JZ2?`73 zOHEWu8|2>z^X7fz-3`B%?dQa~8!3{t%8b6rk67IS7Q&CEoF&1Nb5ZTpY4GITLf46q zBytzr>ZQhbisQ*W3$0KV&Wa>*lf*L=-r5$57-dURX3DWs7M`iNNuD4xBx0V^u$Cef z8?t}yCAL*3wyWd$ys#67d*v_9k@2Qlh=~qRgMATATL^(SRnF(0HCB4Wpev7)_Xim} zCzAaIKyYXf!duD8e|&8l5_4r6Fnzj5MsTvnnmZ*Dgzp)FD9{XO6`lkNh==@m-MTy$|4h z2$v{?&j7$Z(qQ>JN=Yzq8}QZ;N7&{2zxZ=0ouXoXQ;+|U3;4^L$bWbw1jh9K)&oM9 zr;^`)vaYV;Aq)n#(LwAA+Y+Hb`_s&SvfKFt2YCjCkMd7;i?=NjYMmEuB?$D%Y@OpC zem&j218&3g!yq;(+$zAxpCQCaD5M^SA>iOjL0mVcoAGzkC3b23kocq?rfgr(KB-6S zX2Uy6L^`?xG91*wVPE=S-{076<=|e6ne>!MWh=hngVjkQZYmm1MP}y2e)+_V5dZSW z2Stzuuc{hXc)MMZlECtte|xN>&n}mPi^E0ghp)@Ec?CHKBIh)h7jUJ^9AEVBWB}~q zYcaqVX5i0cK&ACRKNivqKNuLlOD; zQ$L;CX`6lE|CM)ye)5iPz4eZiG#gnm7W7Rjv_HH*1VN8hh*pSakei^DAoNx#Bz z`iKxPgM}jVCkb=xr8YYAaBpn_X6XIV=Y)g!zu{tRG#w5&K6a4~sb1$t4x62ScB?OI z=#Eb`GE!wHKG$@cyT+rp%9a#hrApL*v|cp-qtC(f&+`x;>f5-o9qvBM%Mq*kcEDkD z_u;1ldA3m$H&Wm6mT&;y5xVkX^lp*5*#Z*Wdx(?~GXFIMS5`XDgv4k31mjQq8w6gc%euai^A z382sW3Zu&3!@mGpsvn{YVDz`1+zf{d^#$L~MPLaE1cX#$|Hby;wY2#5XWUhgTo8l? zIT(2mc@yO5@_bR|XQnSd4ne0il>`P#;WT|AZ}weVIVoQ5GqF>6TXggJod$Pm&}UCJ zBWzM7|4j?15s6o-AIVJ77G-vSHFUN*NX$x$+I-UDP96WAnjald^HJ>^pf?Obc`9P7 zG1)4*{07{aB=vcU-MWCkx@tpQ?|`fQ5$WEqp8`q(-u!o0R(y(d*pV8}{}FUIwzjj>bNHX}J0u4?wv5lD5BcW|O1l4t`-K18|5e_|*3s0?$kNEl z;V&dPQNdE?GxY9tu~@mGyh&mKhqxu%d@V00>tJBv8_Q^#!l0`8s%X|5SJiK|SI;9R zOembcQ_nNza`8DrE7VrXO?rxJ$~DX0>hkUSX51M-f=mdXFMJmf&8WbTGgKc%Vx5W- zBV7I$xd^8MUGH0%AIQTL>ep6p0-|C3Q;o*BTx+_4rt=4!;byF+C1Y8~srom^C5y&0 zwEhe|CakneY@F66VY8 zx5Q2xE;>xx^i{TeiE@q^hbcm0NlQ9el-%0c=K>x5hQ&PfHYkmJfHP%^juEF4a_Uwj zd~ogz7de6L<`^Wpz;-p^G<-B+>MQ#zX)PbJ=!ri!y8O%$^NFvBOjcvYtbR}9zNr5t zTFVEGwK(kbwV_aPzm~!urT#;vQXkWt;v#osG9rvVqC91rq*n@Q52im^<2!_!)m%RF z&|GR)Erok<(_pj5^VT!W_!|f14~L7g4-d7Z5M-6NSjoy3(WUPR7rG@WyTAbZq;A|Z zH)0neq)*0(^86t2Er3DfVHa^nG7Zr8kiPaHJn{oJ@fNE4b^+N#mAGDzfVG&B5-U>> znF70yJ;bk;bw5F&oJD<)OoKGt>8B$SP>5&I$Q{5bX`;rYFD~G=a{RJKc%IGO9 z5do#*mvJNuyz5zPgyR>spsTj~$nrIHwQo2K?!B_*N|j>>ji>PvMHygwe3_&4aHit)-QvotC-cNDLt4@EIy$^EGbK0IU;KIw!?H%7mm?6WU+VA;_>l-5n>Dg^owRP8DOZ3F&&=AQFaMz zp)%@$^-HzIbg=3N87F1-iQxJ_bZS zXSTW2f9W-d5V<0@ZgQ!Q#G!b-$;F^yUK^%W^)KGlpd2gb*>pR1dDS+^SWC6ChhH-y zZ|S-f!3a8W_E83 zP_t`n1ZqtMitPm4rs;YxSdD{3O!MfTS&L^3R3|5QkP7Y{weCid4#Oe3YRcpjJ_?s~ zlgtmANyt3)^M9va&@8Uz6I)gQn)TX}u+F--7bK2-{jy=Gwkw3Z1Y0)PvW;0%$$22p zS;g*eN3w^fz_E~Z!p~7;tDoj#P~_lVl;tGZ9D4Eti-BHJp>kfnQ5dm{N3is#IPUJQ zj1>C57qHlI!q1>_ ze?7z`h5qRnQ~9%Hk~`UOu_Hzd2ob0*RTn}O1uzjmMkx>2S5kHNJ*7huH#HS~Ya##y z6&3wn$+EFAe09|f-FBLHqs(%_Oyi-m(wybo>cPx%>f<7vE*b>V>+RP;_d|yJz5CJT zP1f_{dvK^pQ_GCZ-ibC3xdWc@8!r2Hu_pU*@#XZJF3)x@I6e2ify=VY-f=sw+kgz# zv7AlUQU2u|yvHpDS5zY@?>oYNdGAd_yV&HNbL(DKoQQpj0wi3#|i zNY%trXJ?VdvKl=zCCJJ7g_169^Xgeu5;@fQRid;N1er9?O3w}TJA7CUzcO8ce5P{k z9xv!TX(qn>Xo=daPL&vHVOFh3!WSk*F#D$qZP%B z?;3Urk~F>>DI(18tf1hndeQALt*MMwaFj2F<5@H-!q#~$J(EW5=mpF!X3rd z=41<6xp2@mziIXNPc&mJ#4+x6omAh<+*v^nnro{Zcb`Z{zu3JoFIGpGiL-ktsLDx1 z9rjueO14j494X~R!SlReWh+)5R8~zLVw+g18%Z;xS zvyzX>1K9K`xoansP@d8mBxE*^wekZeyD-ry;GF*7!3|@+J1}YGPd6X0RSe@N z^~}l7RD>8gH0Sj3IalPwM?2Od%-RK36`Esz8GBO^ga(2FR0pI4pad)jC6 z1*pnzh}pyG^3^bwbg^Wl!B2ii{Z|CnGVc)XGD|b`{H;Yo`vwII=UCv6iCL*J&k}^yEfnCfZ6!s5ILIET%OI@%c<~-1~%GuTos&Q7FIQ z2ZPO|paaS@bv@9G|p?3BPim?kkdF_IOonl0DixFc{lVi(q zSIgAc<3Y=xZ4NsCz9PNCMJQI6=GEi8iYwjJ0v1#2Si-LgNmY>^S0%8_2UQNYocX z7Hr{D>M%gnV7^G(=39}RF<(!MQ9+gYr(XD0`w;(B@84JDCHqCG>pDiKK+l+q7MiVi z&%ljjL-!Oy%J{Chy*HhAz2j#@qGH37SYrj*rR2^CagAlIAa!kXxO+t{Q5pJE@6_jT z=hKU}U@nKcX8IxigsZ{W0`H)yC30Z`{;Vbw!egIQ;xXSL%o0{8T&b{RaI6RG`e^nD z9b{gkoj>}D*yS4n^*EP~MTO*msz7A&ITeg@w-vrKfXS+Ec=Enw5Vv`CkJ)|QDw^ZW zwwUXpZg}IqWf=EiH6Pv+SHy-$q22|B(~S~7j#ZTCUQNz3XvXpy`lLQ0EFm}j*mxZ1 zAzI-02qu?jHP;*3vv>A`&~tQA$NW^L(j&pnx~OkVgseGR6MWP&hVv!mq%-wb$_bZf zmnYDoJ=H1kzCN}DE`<@^o(bni;>-Y*wZh4`17&pcwKq*923OphU9iQA)`Xn;lM*){ zO)ag|`0FQieO&Pu9RwVaCjx$$Wh{eTD-C)XAI` z2c%5tZ>2%x0W4x}Mb#SZ5i6P4B{jy*GoRzfTTAPRHu`5ptBZaC;5>Z5IG~|(M2E3X zi(wy2vL}8R&zUj?qs?eiP9vST;7?<6Olx|4S>BnfZx+#eFhJnviR9WByO`j-SIBJq z7G^1TMc?T@ech2P{Gf2MGi;x`=OXS&dp4HsmiO|IV0r6GKW) zET!N&a@4u)OX*Dr4;lwmQ0f=VFLn(kwU?_Z-@%v28IgoyJ>`HK6+fTCIJvD?Q6N6& zfCRtym5E#Gn=32sJYd~QQ1 zh@pMX&k9@4eUa976R5(a)X=7WG^rkr zG_1#-utniOu>V*>8h%p$x$JBF`6r1@M>%2KD1q9SUSJ<*EUeD4MQ)M(-XM@@EHR2q zg)L9>Jfv>&nv#{}hO$PVTV}|^tH*NKgKu%Ai|*7y$8gxfREw%nF}kvWM1tIcQqAvN zUKX0H$xuyMY%JOVg&mtXlvR8-l|0l)C;5H}tfT3zit1&C>ZR7=e-{Aj9}rLmorvHX%u=VAfvH?_>vhS5wWcxSBIACOVTY#y#V3 z?JV<)wOD4pReg^AU(&kGFz4aAbc@lp;S#28%PLCNtezgPYCc9?a=$G*1$LXfBj~*N zQOL3$cw5w-uxXdgYu)~Rn&X1)w#pr_vzNB}jO#MDf$0Jrb}^sgn0^)iCwk-?-amh% zIB{od1JnP;~i6&2XUNs*7@f>aA0^GHFE;0|IglFyN06i(j1P6M&7d5)(ru za)r$tPe;dr_5C}r%T}1(Rt~>q=jv)1A5dbL3Z=N3H z)TR5wL)Qb&&0*vRr*}vQNvIYgrVy<#nJBHV8{5P@B_eyUHtb9?p#!Psm$;=qhm@#* z6Gu1TwrU?wWE+$#wC!@AX1!l4+6LT2yX~|c!6q<1`ysrN7;VQUrMrpxj|lmt|WS@0lL9n!LBp{-f@6lxdpv_ z_M?4x0N*2cy?uLi^sZP&-r*j>x3hh``ChC|K7fCAOG4@gB20u))vV|O>)Q8#^#=7E z`oa1~0{jAi!q1i<2J^v$AOk?@%ZI@A?|}o$0K)(plqHh}=YX*RGyKl)gjQ0|2OF#p zqWjhGh?g1atkvfR;0Tz;$BD6FP8D8j!2rS4jn7K{V%Ot2;%Af6x{ zXhpHApatZtP?y%f3C4nL*)*rfzYRO=ix1R@agbnPj;#5tc!`tvbj~qDqX4zkTAQ4@ zWf8KYnfsUIb}{R3N*tD^ez%)w2Qw}Va%Lyz=RwMtGV1E4;`I&-)7I1K;!I6qi9=Ki zlBKp9GHJC+=jv*-@GSnb%VU_q6zM;1;2OSdfJi+aD?o-R4(yFKn6j8Q<;WFhsmoeT zh!+=lYI~ZO8!M@&nVD~7m<=%r#30S>jWew&xK)%-e*X}zq_!+s#I{6LY30*OoR*9# zRV?0Bwi9a3HZ*rokfG+Pa_onxU|t{&Qtqvyp5+?xHD`qVcGYE~tmtfybM`~FRgp>R zb8-~AQJDFxG4!PayoSI6a!1!#p}I%w5k^u*ScPU}`n(TCC0FX~IarhAT18ZY`lw*M z<%w~64*B4(7>u$NWr{!}gJ*>YUZc9eBOHtcDN8H%TETjKRSsH$w21N{pu~qXR}~Dp zg@F81rquLkm>D8G@-rRo6|r(+d!VKC)0v``til}7LA*EJds_bkR`w^UCQO|lDwA5S zH5pT3Tw2p-(e#&zT?g~DYDI(Rb@b3JY4`G6fxWFJfD2~*?$g1wIiq;r8#xDg8w(2= zQboT`VrqR;XZ3QT-}et6zHJSLbZk9TVjVXgp^nD77%P`nt2% zBe&=w!vwcNmM5-Ad8_6oo=Yki$?rU~5tc%142|hpwhYBZZH8(Kx`BgakAjHmNIyj+hZ5_T3M<-wZ|VltbXJq}9R)|W0-yqidLpfOn! zuPvToIl&sxin3uN>O8Z_W$-4sQ6K@l8om7lv zkOiq>JN_Dw6Z$fEuN7$cYl_i|K#b)cwSL%2aIaPHyKeOk%#fLpgt+{HEHay?DwJYk5oR;YCRn@~5qSuhP1G?+3WgwXg z<(NNCm40&Szm^TUIg$6fcXM&WXVvfT-*HvTwR2Z$q`j^m8QF+adsk7vYZl96^5nEe zF5Db0F)OP;V!DT+&)}gNnaQkiaYwq~k3Fk3#jGjXLP=q(>~;AV;95&OVlx&bvqs8D zN9KNRU)I<{D6h=cKok-=;cTZ*Y!CFXB4occWJlF7UHrukHs5TX6lNxT7Z62U-?!vT zaWPTlDyJy5B3D@`RUbtfr%+5B$7v+$Br1ujHmtJsh5*(Ih6?uZO=z&I2~CO?j<+iF zmOZWaoq=u8nW}FAQi;Ww16JOu4u`EA+fw-Q(qIUX^*Xuxr9Hb_mI-E3c+G&cH851P zD^!O2o1;2KVUww}qrZ}vbe~|V4O}air9)aXLYp8k=no+s3aR&sSV9`DXk?_QYnA0)EBb?(dd61@!7`PmQ@dM@J=dL)A~Ybtx=BUoK=Zhf29Q`)SGw7r-uW0TW z*?0Ft=^&7eeoeFuiNIr`6u3R2^9b{G+e(fq`{BEbmR=l|wmlN(^|L6Ab=z_dEBoQ| ziXmp|S%nrD0~G#3n>g9Jh> z+b^|Aw(=KLgQ>WfToEiZGl7`tUFks5qhX%6`qwL7*51$AJ1jh+BN(mEWlMN1yvujGn1 zIQ!1>EeV8LiOsV1;t(l0f8d9@2w)tvi479%dXS2J8~fl0E4) z4058A&PwV(Y$$l*Ks2ujtDZ!wp4h5f*;U?Ps-6gwo9d#*(YgaDyZk7-GAKV#Ro>jH zo{-W7Ma&pF1r(0F(oYmULo0M$`eRzr5VvUiJLytdF@(1>Cxi#InBH8KZ>kdQr1!hp z^IMR>b+$k|X=th|BZTidS{NBff zp~u$;^Q#(c4e@c5w3^O&bGXoga~yYoI(n08O$ik|BV8f& zi}Z>xibn8@)F~{u_NiFI3o@yb8o@y|&(XS=$F3_0zB+KSzBVMDs_LYG>Iq@iT#rEZ z-jnm>EB%i6O**sRiKZ#f;4WN!X&TQp9BVPkH`Mj53uXeH;ln}?XnC1yNCG2@dq0P zj)I@XDM=``0>YYqWDu%rBa}HFIZu#`Hll2l^F)`?6J zE!Q7kpOGFPpBXgJ(q$un7f(m{0o=)DWoRMMrzyWDX~R<$EP_xT*>16LAgfAML$XX~ z_;EWjT@iQUE{R-%AxyXX_1>}Y9@OQ$6LxMzh6o1SZoyi^U!dMI2EQZz=a}HD(*Hlw z1?<06W6i9L{);lcr##eE@E2V`{;QDs-}TM>$2?^{ODCiMPzTM5|0hS_OBg@ODFd7& z|7UovBA#b17Zi^#F*X9@ntB~VO{6FydASL-uNJ z1~mP2#rx;v<%YxLI(O%$k0&>nEoiw~=6{kNY|^5ZHm|8d!{??eiowo3)iNdXBHI}Q_+Il zhx}ozHfM3TW3*8xE>d+PQAsHqM&d;>zr5-*S4|7%6Ry%Urxf9r(JrI5RpTuv9>5tr z;Y!#;Oj>kLEc2VP?zNN1m`Sr#bHB;MIB0@7I``gNgwz0{Gj)z5VwAHnoM#`gWBT90+f0E%A&sOe=7&DVCEzIj91vH3B?X&O98z zHeNicG>X^)Xy_O+vt|BJ8NmtAyy3#DXf?*Xi6vOvP^!Lkpw!2Fwtx>-qyKEbK9Sp< z*NIXQ+MVac&f)kWVbUT zMoUguI31&~2MTs8Dht-}3gY}k{R*vx-=FXlX(;a#vloD=5V&rY2&G^pi6U+__M><; z6*%T(nDb*Tjt2H(=n^S2>=~5d4!h@P8-1XiWUS1LmL{PH(bpa6`lfpS#i>Z(^zUKIU{Z5``0sHczC(o>(Snr?5?O z_+va#$_Mm+-T-MC75ZI}-@eTteETZ){8zrre_F`@qPnQ4$>J=cagW0}GBQoUft*9+ z#ev6HOrNMiPy&941_Wb;K@=jbr04nZ2_RxYP*3Qa=w!{SC2~((5F_x16{d0=SG2 zRl!q{YPgGicSN|n=p9wN!CO+eyhxsMebk^L0(~ZMcYqrBJFFvCI^C@nKNN@=2x$N& zlkG^48K?pcQ^v~_0+HV!Al-`(7NMGcg3;nPwvq^}%^ z+ltk$)HuIl;QEl?vzmej{_H2X@}U}cm9-kVUFwQ>FByd+t4&Ht z%fPh;@tBZ_L{$AP6lOZJmX74a$TXd}7A|nEjlCDv&`5^Ik=|pJw(cP}1ZLwi9kHWS zjdjxed|Xeyuj_vYoLt^^xQ>2P!5FOLQfbY?z0cfn^os)-XOL6w;CgmOw>OYn>mE>hR|TEb!9BhjD2$%k?!toNhE5=3@*dFC9{ZzuPa)dAAOcO>jp; z-p+EBg%Q-MY&N>=-$+jj3Xd_njN4ToMYn;Y^fJ_vxf9Z^+Fpj~$LzyKGK3qDOblyU zbq;wxKi(4^^-;Z*- zMI{v^OJmfxl8p}bEqfp@W=|e!4l>d^v)YYt#%1Y4OoTQX)~xr1o*f)ENa5;Kl976_HY6Mc%TEV+7Y{Cn&I@yRE-p%=v+GK3lBy@^UES zt5Od`hIaC-@H{*(UGDnE40>^G8>|c_@F2XnjttK7WM5xb#2k7$dg9#B@9x&bRK*bS zM8B|+m{!JV1d);pu}=^|!lM{U2|foJ=V^%yKXnJqWZv?BS1`|hL@5$n3j5aW+hugxhE3M~;=9j5GqhkQ_pG@iOtU-O z8kK074O=j8yb`rhylg&SUAz*BxnfRTPKB(|+8F(w zUxlJgd~RM`i|Ay9lFYg_pfRj+v9`(t{j^zYP+&FZ5bss#q{nN7-meqql`VTK)Xveq zkG(KAdOY86(rj<3XS%O8j_7Y~*sfmmIAilvCPMRCPqNC>TBSMcsv&F)nNxeIT+zi3 zrxJM=yM1dn^6yFW7&S?CX|0xe*3E>GR;p1VHF$D@H35w6rRN7Ow0MIBOEH5jlU{2k zl(1b<{hc}Bp1%E<27jDt0udOjF?0?Ix*~dA!?RiKz-X@(U1E2D9&pvQ%-*AxZ_(6O z9?9?cswY1BZl7s#A0zf3*b+}UkqfeacqvaiWpUxP|l3qM0~n~ zbU8XmZ9zS%^_mG|AkgSh-4x0Q%Te7bB;%OF&t}ogWcTa@;)I3NE7`l@!yDBcqNT#Q z^~T+-6)n4!s#FDQSv3gyS;(Dxe#@Te_3I~>EgAQ(REqaIlP%~ekvB=z1}Hb`--kP? zC+nkyJE<{;D^WNP!B8q!F6osk*8=)?7GV0#(N3FAP*;nVkjk}dIr@B$gSR+alNXOVncEomX_TR?Q-c;lWnYp_r_R6YCG4JA7D>C{&-p68dFI z4fRldtKJ8iI|Kjd>!6q~%?8rFrpb(2f8;g=m9zVyCBX_{`Rx{MTq4r zj^AW1{cEgvt6#1c6!L7NO-;LpR&mRbEXBPMlH`hBeuc9*cE$T=RdsMhJBD|M;0+x9 z2@=rwlcmNvqe0kmu8AnWQ7>U(+#2?YbCkTJ^>ECkV|L^(tD=q$C z=&}w*_GWsPX6{CY|K$km=~E??B|X9Jkz?cIae0}!*WB&>1l=>*f+7TRNO&}m zk2w*s&5w#vi@JX%kD5|TWvr6l5}rg>we1eY%J0ew1Aq9}RmQW6HnLp5SY+Ct+3qK4 za0d)H)E_7V?r<8t*6^qwECO_BV50{j!63l$Tr;ax<`Ec>MMju(2ecAP&P>U)~{GhB1_S=WNoIL#a_V74j;q37}VHPu5dM)-3F3n?ZPEH}vmvH$Cy+o0J z+?Tt191ZpzC7mlz7CrU)GEX(>xE|f|Q^t?6%^1ZZqj zx$4%vW`XlAZaA^CEiDBwsG_^ci>!OLe@BB1+F*x;86KT1)NH=KFS=monVg3Kc?0E8 z;FOg=@dA_Y?{dH1APE1(<9%kT;*1XzeVePi)BQTjnjj8 zr;G4TeNayYE0_c6gNAo}`mP@sz3A7h@@LgZ8Sg0;(R<~qW*dy3Zw5Keyi__#Etw0@ zEQG<}gXu-KE*x=6?nlw4E=%%&B32f2rrmP*p<~G0lT4ut8~ys`n&#Cbh90x&8d`Kg zK*m=M4t}!Kth8i&JVivnJh>dAXbV!nGezR3==}inhNBgw(~l|*3xS$%iS}$RDSfZI zw?nT8AtU6U5h#nlxD|s;n-hD1WW(RR{6>3nxQ6jjPzDJlL$A6=kPl1Ly)#7AP{HNj zR2Q(|x(eDbyYMFlGW7iChbpohFwU9;3c^A^PGh+lbJROANQTiiYN}MGG;G{e2-$r9 z*sepIAEi!hBuA8zphFl%$0BDFgDHY5Wcad2kubRXGLR?j;u%@5mOksqw3~7EwA$F6 zgQLlv_thD(Uhd0Ots!N3(rzP1#mqyBLBefH$#{@1$ZWU*k#P?**9CH8OEL*ZT`MA{zM48>(f;sHo z6yiUd?7IpaC4ElyAD`b)N+)gkIHiFoRD;|7vjn|;C&IHKhJU<_g<4e^Gu4R9+Yrzj z<6-UuFuC`m3YbjT04aAw2zl?NxYnhSoWZt!zP^fiYi*-b~nC8TKn>SM= zG1IbBzx`Y9&>=KWw%`}ojDLX*{r?7R6#fIa{slNm%4#YKDySdU$Snk|{QeMDzx+6i zeinYBXBhm(hBid-(9_ zXsDdKNYg+|hf-Q(ojFWwY;L@+dgSaqetNfk&qdpOrbE$EQVp#1w(NDrFT&N&OXP3H zp3ml0>NpdMLDW9G)8o;;&ckSbJL#lif>Oj&X%HPz`on#u1!)($74xCwx(Zn$d z;SpQ8c_U|E%!(mrp`M%Lyu}59`{8?iuI_N+ld*L3fIJE$I+4R^TBLuts7{7$*&b@k z%L*!(YbKL@z=I!rD^qW7^kS^MjC`q!V34wr^6#mtfXB5VFw`;8Wq0>d1$;aG4B-W_ zdfm|q%9jYts*f{AsAOk~XtGk{A#5q4jAhFstX}yk&+f(Vb~>V>jY@J5m2hOKtc`%O zC{cT^hb5>4xm4F1q$!0Ut$f~DsSf>#nbggY`!h1FKKx$oKQrXZUcQ_<6ujm|QBlRE zQb!xbs_wG96&9g8rNRB7rI@oda584DfXPy};%zo*GAP(eLFGw!66eSRONXT;TPCZ> zCF5*r#m@U0J$S=gk#xAx5e<+tCHU%XCp1##4nI~kI(QpB&E8d4k^XkTMsJJ%0E4Lr ziv`??8cRGkR;%32YD3MGA$s~Llb)AXRJ0QiS)BV#B*$%EUid;`G7_x=}l25*OP8s1e8i}{F z$*{MkG3W7?8P8d#n)jfZ8t1JoyC`+0BHrQ+Y4md7R(Squ@_KBK+^FvFfPi0ho8v+n z&eG|U5j)&AAn_D>GtMJbb0;g9%@$T)c@~>jIIeWv5S7Q{_hr1lSI}g! zuBf267CY*AvJh)3z&uYaG0K;`SwzWni(yORQ@8wk$0~QP07od&BC|cp_PTd=35~4w zDaKZ7Zz2f2YTnl2z84f;Db)|SHjma=iwgZq93;u6!qpCE%o%bP|Mh#-6LX6eS-{Jl z(zl(EF1RDw?=Q7Dl*GCg(6$kvswfegEijWtihVnp7g3Jr1#ogz8DN?UAXRq0<$d)> z-##N?%A7RcmowlX?M|tF?_OM$U9=ohP|yYjjJnosHQQ}Xth8{3>hylU413>6A92wx zkR`Y`pRZRXnfr(}_Xz?0E<(M<&63BiCr>U})w`;p;RN25;dq%W))0sGQ?dVW%aV?}+EHg)+lx}-{f0WHw_rmBi@;jgx7>$MkoK8G@zph}uHs2B6>Dq#h+kdq6Q z)tSo2{nn=9G(HX1muYjrp2>TFdfUerk$Q9H{7w5aHhH6mowDf;Yq?iktYnr9q%nr$&V)v7zf34~ZdU_p)_&BO`|x)mq;+Mh9bxWWv#i_E^; zV)@*R)W9t@QC!P)!bvpSkOOcay+-EIBl~nnm4Wvq8r4x`^N^{~8|>&FYP&T?`NH7v z#`y9kHm(BFuHtS@>-je+cltICCgnRBETt(m!DU*$93ljZR{f7UX!QR=Ju0+_N{> zwwIZGSg)%;P3T|Z6O&r+kY2|IpZt~7>xX;D#dG`o6YP(in=Re%xNrBH`1qhp5tE>% ze|>}heAC1%?Sbf^NXh$_5+To`87AQ>MN@6DMBSfK^c2p8Wsfx-3zZ8HGcy^PRceid zpo5_FwZL4Ah0z5${&o@@C!tIM_jDZ`oEh8!q0z%C-{L+$1`W2m7n53jDG^Pl(qx~H`+;VGK*mrBtHb*;J}b80gKiUd;tzaN?zEVX~yQT z;*QM8OODcNS&Ip#5e~|=jZw_KI$Fc5zM76+|6l@}h+N!!H!Uy@Kxd!)<{XIUF*X8g z8AHl|5|^1YUOXmBn7~Nnmf%i)TAUWyS8U06iMquSFXop#b$dMO*+F!p(8G+g%Mg#O zI&Xs=cCAfRZa*cf3&=~IVJ@VGE&0vLRAHDc8_|H;*ITWb#Xt(a5Uf6;pNB)2o{{xq zN*G3&f*f1Eo1as;gJWo-J^&5~gKe8i@Y>&!=V#ea&cA(Uuy5PRdQ;_vtOZOlqjNuB$f-c@Z%giNAq^L ztV@!(38^!7C^jccVP5ub5+bb8$86CkR7XAl0;0~!U2x0AYXs|KR}4A$%VSr3eAAZ7 zU4b(c)y_5bUJ(wS0a6YgA;m!xwt+ThXeM4nzLY0UM*DHerAfVIo1($6BM@TlrZmPg zII+EE@xeCWd74UGCobcS*Fj;WsB;{cOnFREBn^qcxvpuEqFRtUYC)vsf}{iSssJTt zhrQr|*repSq+A2)Y*~ku^wm7QVG2sxS>mr2NeFHuL5iFKldJS)bW-75<3AmwRv88M zf|TcQA|5({~jqHJ%qNNL?R{&vIDSnku3k2nPF zp+Aam#La1HJUPXq`+LxF!6JD>ElyFbZT6xZ?7R!NLOE3C1GWMn0Xgq54L1_BfPDD# zHSjPzyUdOJq!15>Q#en?Dfd-xU!5&jFt^elPvCxCwy$s$C5Io0^lKEtm37n8p-NP_ z;bto3Y#DBwP_)i^%_I5CVPrD6T+nB7My=U@tMx8Xm`V+`9pl-B6;d2=9=L80Td^k@ zFZlJoJ2eL%SSZ!Bjhc$iVf_7S3eIeMShGOMuXcODoVKU#m=3IN&1*x1QxhZaaDR5rU z43E-H&SFYBfSLCb{HYIbOtyCf+7;W zmcOF>`J6io`mzy1xNjWey_~6Y0&zRIg0lAwT08zk4AdnVU{Nt953>7{idHA!j4DVB z)Rm8^c16za561hDrS;hlaX%*WdAGss^*>g`1ad35cXm0G)V2$6kk3G4qo_J{i))kLFQVX9%gm&r(!>0`4?t0 zgCVI+L1KUE)EgD+)dAJld@_;|=c8;=I8q#=XChx!pbW8Ge1ub}vwEL>h)_q$xHVkk1R6o5YYYHw6FxXze! z^~_rAO63?98UO7&PwLZ7#Am;&u?ux$zqr_0Z{{-N;p>FaM4I>W^D(2ZP{rvKeGySa zW;ANC)0nPuNEmx#hDsZFGpR4LL0GB9fMG#;wCJ2)=aHGQ#uWWu4>g6P%aUd zONCez97fhQ4vX@eadnHE&0G*(qx&=Ut(Pru!hGV})=O)*U|E%@qtf$^mFnZ@#>;j= z$Iv@9l`i^=sCC-+VuM9lRLS`hg?))5O zBBq{i!D0+f21rlfYJ;N1b*)5qI0O$}L0cNXY$=(-q2{c?RQzvIt9AecsVBanj%kK5 z_Nko0Hk8|szP7|nrauP0K;K`mbdoULQ!qgipU68>ka9MLq}VWkTS|eXKO{>HZ zE29l?w3zt$hUjH-Y+~YK;_Kq!t$)vk{H7ajv1uJk^hgs+v^V5=ZP10I^izG`6gm2s zWN^f;FPhXD%|0cF1sgk9}IfL8%VmL&;Lj5c&U6mHC3AUly*U#iFQK1Lqvu+JsG z9rsXxPy0Srl7sw0u0&W=C=)g>o-CIGPOMeh2LQecUR3v~12K@)ss!8P(FBz#YNdxM z2+Nb$B!~M2Arjd%hkwQ~i{pHGVZ})#vdIq@3DPL+kO5CaHLLoj#qoaa`HABc?C}ZW zRrJ-0FHqWL##4&^kl%3ysvu)2?|=cZLmLuRs||_bq{K5z4H@H*fYS0eKL}OG?dsy? z2sIMfgoZKW?10irbxA`4No-QXU~ytVX%z+`!wh5-vext=X7S9jJ$1s>BsPg*Cqca8 zzGZPd={+QIOW7My!Wj7-9AFH|4JL3x=|+_>Mq!5w7(;pk2Aoi_=Z+(#u=9&2MRKb{ z#-MP6i7TP7i;FKoa%)4zpmc+XGoi2xi#I`XYeG(;X!RR%NNkZDb_nB=2^&q~${B)9 zY~de<4eJmMqfF{Z9g;|F5g(Qa>yQj9PwL1VqD*WN9;OWI5D&9R>QE0mP3#B;Tcoh- zj9)}@>qKTHa|4ZIrLZfAXGLGw^lOZj`d;+9G`(8ye6eJsEn!W%Q-h4Kv+VUE%c9x#XK#tnF(bOTPP zqqxHZ)FHev0$!-xpb_dQ?R*F75ZyQd@f2_12{#pY2!NY}H&#GA&p_P!*ItM?SJj?~pm#+dinurbUWquD*i#y^4EZyAoDSJ_L%a_1Gb=D#?&ea^ zyQr^T+*@joRh+A2uUYUzAnY*djWlkP{MtW$6XiJonU><2DDG2!2MGL>+LICQsMzxf zeNzilNqh?$`lPs~*#1m(l^WIwdy@)VOj?uPyA+=i*UIh77y*VRigy%g(hxc%x@xrA zhm9%h;O>u*%9CGL**g){{R(?bERPj!M!uv}aUt{|yY{ocC!Uer5!k07oKf5%+CLF8 zv;p!cSMdlwDD9x^pNJUx0C|+Ez6&BK?lA5H1ow1-JStTLf){*@*@>5caJR|*KV$nV z38i|^Rh=+`bNd8Y+r%53o6Llp%<{kZqzF+Zgayi6`F&UMBhAH+oXV?@_V%`0tEMd$pkvf?)_{6g;Vuc%E8nx0>3Va;`2b-#A^$qNL68 zz&$8&An)cp#jJjAl~a}N8rAkSSFGS)Ej*P^If1JW5EV&11^iLh>A~`QviAwiGRTopd5Ux4N#uTP>HvszgP_EyyL!_q$e61L%iubz$)Oaw~N` zHD@H>E+nTi{$1XvtHcZn+zW=HyM;L@8N+P;FR{*MK}cyE>I!IA%7B(BcgLg$cLFSL1Pr)XA* zcfQNFo3ru4;rQy=x1E*WzpR8HyXOvdYHErN?3h2|g_g`(QCQO0kNW3l*Ix2*dc*R| zIJRyVcAUYz_KhY`EvA+H06dD|V>G`j)KBQ59PO8^`dmkAZOm}13*&mLP(Q1SM9Cy2 zQctVcH5WkCp`B>{bTKzb;?zwySM;fzgAv`|sVqE!BsDZ*l0;#Ga`k?*CK})`D^NHW z8r+?@nYPjdl>XNAwYXMb_(N?~(PO;UEWIJPT{ngU$6Zn(D=NcyzO}*SD&-|)M}kU`HaJjqqe=bD9N4^sA^sutx=@bXSdJ#P*cl@wZpQJMqyF+pXIZSS2%V zAb7e7hI#RtP8iC0Fr0N5?GHzQEh4VU9+5&cqkeUK7mAKF;smyIB1u3aF!9ATcst&{ zy4&A{evFjWp+;0*L#+Pc`oR9>DE0_vic&-Qyt4f2m{bTSKPiyQ-F~2S;S;DdQOptO-k_$2;-S%sUC;5fG(O zuOuuY=8YbZ9EYy3$_H?YDeIS-SSVa+h0B!MecJ1S3WI%;W4-v9?Uh;xd+jI}K9T^m zy0E)rqAGJ}n$QGjwqXmT-qBMv9It$yPp8M$Bqq%RaSGX(9!Mj!6Lp zV=or(Augz*rer>B#mDOS0~39qANKT#%^av!1%J(NN~e7~U7~jfviHdIAPJ!e^x3*GhS8+Kw6bZ|szp(lk=)NC0Se-z0& zV0J@Ha%e^N+pjiFzZVFz9K?;x)GGF@$p&rG>*{ULW4sF)CcY2PE#e?{>LJR+#S-D5n}{ zWQ5Z;EI3yIUmU*fOZL5(JZT#QGKI@vc3arjwjWYuvRs^!#Wo? zL*0e6dC>k~*IwLGe9&Ipsx_;{xK@>B@2df*Bim#iJx@PR-$f^9aH4wGl;G7kI@Eh{ z6Kv4C?=Ksg#S9m`4o>xLwlM1eqK3K2U$>9~Vwk5R4f8ZANY4Gx@=Oi5ruCV}Zsu}9 zHl)w97i534v;U!9h!ws(X-b+FU8)~3pJX6dkY6oj!09*t)e5PV(DN-?|5A|45}1J3 z#moN>pKXD6=NVdxdMX*>WJ?Rn$Uq`xsv!8&QayervN-~>*)P}A4iuOz^9PyUpD_PV{ z{vtf>w9-q{La-unK|<~IQ%n7e4RwL@0QhY}mrRUwu5`)hkaEE|`iiXmvE5v^k22H*BD3pXD@?IkTh1o@O=iKe zb@f$%Sm0fz%+Dz9clwS=q7H>!F8XrvzTG~QjvrLna&}&aWgNwX!-g42JqsvhPPT4^ zz<6d;ltOU^#84TF#0bv$f2K*$ND97lU^Teuhs+d6yGg_zDvN;~^ z_N)WHi2>%KmEm=@+Dks5I`VmOecf#7>t4kL-;J|`={f!bS5^UCxrxyl%9iAzS?HA6 zhXAZeY*3mSdRz7`FM}-!R_fC5w*x#GGQIPzO|>~2!xA9_+nMKiBKf}-O}2Pq;tVDU zFTOOZ36d$(r8R!24@bXy9tAl-^A^~(w8n#Igndc*$|!KzZV%i^q*9Ndw^_#0PSd!) zGk&yMcF&0y6VgX(t>rprlbvwx=Dy#uZPYi45-pnt5vd}{Z*b<1N+B1c8L z7ze3i#4cP_sgDylQUQ^?RPzbM_b}{_6vl|T#i&#n4`VX38uFt`9gy(xR?>5mZYshG z)9v)rEOzt}3aSc#wgPma@veGI+xKzi2zE?t3&+`}p~Ph~h0ogj=m(Anf-AU=RIO!s zm1s7(XQSV~QeUeXQ|e3+66`33%c^VWG7XJWsaEtI;(y1P02JE7;Rf}nDe7^>2a3jz z{J3f1I?zk|_9qNf9-Bm|I|-_wt~*w28NzFyswigK)6D!Gcvbt?-jPLD=oby3$Ma7T zwTDTZcacV@Gqp3}r=}9jgD6Z4#S|tkRr%QoZ?$9N5w~VFS1)FNW?*f8l=xO)prfibr-lDMh!;$y(UWGu^Yt9upfyrIyPG-P*-A$Vv?|eKza03ELaLOI5(C* z60<21giFXv674hdYrcZt=`SlPDf5y_=tzS74Y(0y$QspuQ@2B?%9f&h&-1&pA$p&# zh|#O%K(;wmw08sSBr^(2kf9Y@95|m$RfC`qrq5N4a0Iwq#Ab{r*aR0|ZAO!LpVx|8E`vv8_qf*vU=Ccja{#Wa7OFQvQY>uCn-+ZkXR zt=%>0M;}hDjF|j9_jQy47#k=i>jwp>uYMV6A)R^(Ia#(fvi!x^T+dv0;Zhj48x#BZ zt$wr4T{xR1Z>`aS#f?)yaIvpi+4rt#0^G@d0*DVBgWBdeyy`y(J{MtL{#KTr!W3&6 zM6y>RWnG^HRXjaIb*kEfbS-i$aU5$)vPaK``OQc8Hs%`J5KL1D7cL-jMFqTe>TMUe zw*rNLpx!2s&sbzmuxlbvz}(8Fpb*3+a>Szt59G@9Uyhaj^%OkW_swZY5!K3Z>qva$ zj7Eig4?Yupb4t-pPO8E}BXhdojL^sVT?$;%U4%S4S>MT^r~}^d1#h>0XR|*bP#>5O zG6Ou^ZM$3Vhw}6o9C|>xWATia@OQM6AxGdOUio6r+m&oZkRJWwYTRABeo_ycSLVPi zL3UI-k#$RVIINnxXQbgiHF>HrN@3H|Um(|Usx9FZ87i2RpKNVE6+={|N>jiLp5tA9 zCKwjZ-d!{L;rqQ{@ zZE7mf+sB4{Ak$Cmz6t5#%(K0PbVFy$!!mNs^EPDA%EiFI+_T|f3?fbRGU_$Q}~cxsd*ym)ScLYA}V@A#twYf^}_2ks!Z76WKlJ zqIn2EHmBJ@ooYh{2%T%bC+sTOaJhhhYltR_g<+0Us5=Qo%%n{GJ$7~zKs)Q2I%?D5 zyL#lH-=^y*e;(o)nROX^)J3PAs`&G`T5G~q&YPg%M#K}7asH&mQEF5#!rORIP4j_8 zu#|EFRD*7wX-A@{zx9mgpkn+_OxBK~+}XpxeMRkEJ6+hU*a_)0>6__|Q5VcrGfb7# zOwmjUPC{El7$>ZxP6rNYL;j@ev7 zBF-OG9re|(T0GMe1OD!;J`KN48`-Ad>|ZZFo2Fe%d>C?R`-wiMVqocurubi?Z(=r% zbC^-_{D60Xr+W!^_!ye0tXC8Gjk_XGS>7r5A0}Ow1xg)w$2KsxX7ChfGM7D56&I>X zeb}<;f&$dk*Q(cVVzXd-wM+T;ICMTGn;%-0R&2XioN3oN>b>3xKSdh+e}w#9d54%X zG5ppy4_GwSEU(qt<%kL~zk0>sR@CJq!Z;}u-1Mh%*AY41V<7A?5scEtcP3$Eb< z3e4HX*N#yprd$fUYJkaw7QS6}z~sDZ_P{N(cJ4KQ6oy%c>MjsKJMWq{Fv_f*cP$>J zV%DL)%M7TVcg-3&W!}iW7LH;y>rmUJ2H4EIW(=${Z{*n(3~(~90KOhe>>5XDFj>#H zNbRlzE~j0q2VR*rs;|FCA)0%N?)C!kr=Lm(2AO!OuA!r3%ss_-X8}3WPZa})Ogz=s z;8C>Zo?^SB0G;Wl-vf(GT~*icQ8wnD61%H_&FQDAfk&pU>TA#_eDgQa-9Z5F^i$cu zB$Kx^6!_iXPr=-7ETk#?u+&fWW*?$1p<~|Iy!J^iBatFEDE467dA9^XGRic31V>xuTG4VU_w zH#_4;clc&QkiKPJ(;B@C-$tbtM^4f_yNcx@IP`Tp*t(nlMW%s(_oCnA=t)MwtN05i zmbu)f#vkz3P=&!r+zzxk%v!9rD6H6eESLda=uS(rF*UhnXqaZd_8W*qE5D1OD1tRO zHy3>o3`7<<)DP|80Bw*UTXxhxXj70?ft}mtn2?M4AyvC!uC{DAk}_cA$MNjZk_Y)J z_J(*f@4r5xwH$7Zyt@<$b({ry(AZZ=VO_z4+`+XoeGv3nHT^KV(cIV4?7ma%Tt=}q zXSm*Vjk%0QZbS__n$=tHwU6Shl-1v7qc2Z6jG@y_fokNMl4`WGkM;_+WM(&T-jxVj znF1!FSJv1c%Q!I3FPE9MtkzPDdb2k4%to|Vgvq6Yi!bm--!CB)_!o_MBBOnXEz&N= z7}o2W&jjcRUq`$-!Pd}^=AAfX&ZxEweb|4wWLI!fo~?Oc-yN@fE?0brKVAw0(=I+E z9?tt40N5`(mr7HsdN13TUls*3QMmq+7N3q5-TxSz`Z`*C{&Uddc+(SS7=mz)q3onu;fpW6+xG}pq_|_y)kN(-Kq%1Ne+UC z0vC7!SGtkt%o=(fL_D~rkWP5lMemH?S!XMBY z=$AU%7#xQq*8w8KOFAT@&g2_RK@OI_H}F=kpnJKequ;ZD zzQ<0L)1X#mh2$L_yf}*)s5R>toBRDEkBZ|qwaY=v=;)b5n$ z*GRL2_c7j{w}1i1TY>|8;}0Z*;AgVi82Zl^`dLr^XVNsEkyIm|@i)dXUW+l79D@(H z10A}9R9c2lwj1jjJ*Xv+oXMl z)b_lQ-fq%=cGgb4`90&OeWq-)evZG%jC~F+ZN8;F>!f~G*ABhm-*z*6X2@OSv)df9 zBN{GW3I|R5{?!IirM5PS z^vIfw8B*{1Edr8bhi^cB7YZHG`1*%PM@a1$TYSHO+L>LS2f%4SjtXyJrxWMe*1!!3 zXZ)s9jpuJ%3=;yGzkw=G_FCK&3j}pAzRSCcJidl9xzx5tfVgU5_#KU&q&w+DRbZkoJ!|t z=v`O=DRbiHU9D>DRcP7Jek&c@B3~nAzQ>gU-BZ`jkc|eKn zIvkAF<4UD7a$8MkL-#9e+dWZ(%7zKH15ZO!%^c+H`l8yTnr10*r-!3FPz3a>8W|I* zT#+RlZV`hlHQ2k>173~|CMOMs5#c(42`pzi&;wzeWnA<)k{D9}4h!|?eZ8I+a9TBI;=>+<*~pA@IEUx3_Tkx89{Wtz7%jmt7UJx z(ZD-+ku_WVUUV!Pesqhz1Moe|W=Oqum?Z+K>K#yjeJXYYl2u#EULveZzGO?ki0UYq zG=#$CY8bszm?r|Mx*b6O6Be#;y1u|6c;nS;qFySjO#Wo6zB_OSOBV>eN|-8w@wy!t ze-A4cEInSVO~Gq@@i4lrz^Lzb*fVs_d>}1?JBxdOoN-?hIF#ixtX>WbFTu0bGlZTO zmM6cOVP6&aff^v8k}g8HoEa3FKmzqGe5ut8j9v}(Iyj)lJs9w`U~Bq_0v*(aKg+8J9Q~uI z$tG1+eRruWp+f6GHRRIO8?W)1R`u}(;;2#anbvX<@%6(7z=M`^LG==-6A6T@YOr$# zP{Hu~Eo*+@TZhpJlu={)rSUbhgcSY}cGyrsSOMm43K2w&aMg{pxZLJf?c1jJBURmv zv*qGJyQYfRB2b~`)(*w;{Cd|$7=Wct6Dn5>;+fZbf3_lsq_tRlC%LmkHZ|YC4&m4|&rkBo!HyC!N=ezu4U>72pY|~qO7b-a%F2v*7 zl|lG%;OGfFnWU)4Q5}?VA2FF6OD|CqrtZKknQ$to<<>2kw5hxE7Ghbp6HxmFWIU-$ zpkxd<%K|;Vg{1GtlDpb5r1w?>;-fRMZp@h)nX{EQTy`^a5Ks86@oVI?z)G8GjUZG(NH;P_>jglwNjO0l~?% z>Et_RrX$GU{l_3d`!GFaYYZU=IN!u|qJDc>AD2tz>C`qD*a;5=#1#9DW@s7Zx^6P)-hcqfoyT7Ib@^ofh=3u2 zOkg||Yws@-*qU^Q5y1Dp7$0D*z*AU&`pCsLE)vi-UbC4|w-?!)=S=YnMZ+fOh@q z{BtGqxb!qc>g|9nbWMNR*GJT??d<`&wcM_+>kQqILZR$2vYjDyl&_hh$pDR{Jo;8B zR^WkJLSh`7EOp#cUD{zI-sLI3&nV5HXj`U2N$qM}zMqiKUZHI?X|#fj(#6b?^yrJ9 zZseAR&Yd!7d@ItRvUg_BpAuDT?oY=Jf>n*-l}ODF<0ZPHR{L6+~q z`X&?^^79X%1|y26GUcMWUI##5$PHRHO*l&SlX}H={=DhI+m2$$T+xDR%vT8aU^6j( zbl++jXP?94?eYMt_EttBDU{BSW})|cBQe&qpf@3ibfv~My_xRz^$`vb53NjM*@+)J@|{eg(H1MAH3O}nR*qIv7RM5IzJH%yBe2<7 zx#2dHQhZ#?zw#o8HQ#RUf+;J%<`pcC1egokn$f9&C(~&!{ zpPZlW{w%zgx=)|Mxw0AhCC%rcmjZ>0c!QzO?bd&5``W!l^s!~``l>S`ivP2#jf^Qt z?`PSD@%$j&TM|PP;4X;z@0KOG_^;oj`Hj4n%a%`0+A~_(#Vktl<&xaWgw&{Y9L`W5 z)zDnE*XXj)RO&9F;XdU7M&-v7(olrWhC6}U5qjzPcW`l{AD)Nl7=@F|5b?!`?e#mM z>6vhD_QlRYtF3;mYgg?NT7mK&c1000noTPKiiqvz)QX7MnI;l+{8c3oAB^4i#4+uB zoM}viIN}~4ZvtVsnnV~6a9g_G`6%eR@DQ_7TRPyL(u*DWNGF2#(1Sdt4=3OqqQ`IR z0uPHtttiPsN^Z=dW1mmJmD?2f$=0FKJd&+Jj+XC^lg>Oxrn+Z|d?<0aB9q zibNj%Vw4k)5UFBuBmzA$-Y`6Q?lwV8--IHWZm|LrSOhC#4s{yBp9Ie^>kvB*h7}n? zib`a8NF1v|QF^s7+@8V97}Ln7T3e^Mh3*;sbY^juyZ5S`{?C8$97!zd*m(Tr%Jaej z0I>Z3I0k|+fcgOXSgZhR!jULv(D*TR zFV8~bL}2d~iYL{Z%`tDJ6>7BR|G|k_Ubep5clZ?e65}Q2J~9s zX+W>&=!QWR2Amkds2d?>ntP~c=kZ?3+I)i?|&9V zA;s{@*H69~q7Xs%%GHm*DWaGS=T)R1d~Ws48nT7AsUFm+7VlEJE<=yphS~gV@ZBPF zQT)krks?!~`&vnwZG=5^I}1{$R4ei0CPs6Tn)B0j=>g=G#NL|zWF;&Ngfhi}n^L`& zYmI7osoZ_mesn;=zISv=W3zehkK~+W*rGRIU-E@IJAqEB;~lDeX3`VP*1dQs9_<0w zldI40{QCFjRKk!+D*$2n$)Zr7&h_zTIYBxFa(QC49yteBnynRQz_b~j}xx%m22CLmz*8!JnM4CQ(g=W5yL7eiXG@WKLdlhaT`v zsW@6?**X~O4d(mh6HFuh9?u>4gXI|QOukn0f$y`CmK;5DKR)f`)kE?WAU$`f8&D77 z=x9@KH`xgJqQF2$%5u~)P&##%UQT1ZFapCB&tObG%iFEDDS-j~Lk-vxbNFE}WU z3;K?(w~q|Y40q60Gy6oFGyRb&OrU$bGLSrduG&}Q2hf)&xF=kAWaY z24!>Pz(hF-<$jWtZXIg93QEB5C1WdJ#o7m+3~$JbAIdv3MZl|HqC?Y5Ni0TP7tf6A zc?h+VMYuu&m<(g(MWxwCqWbR;IAu-OzXYs zu<)7S)x6z40E&RHplrz7BLG1_*buf%-HzS{;nOWt5C)nt`J94x9O?Y=4#|yAwm{hp zY!z}&(;-oD_ul|*fC8RX?ukcWNgR<))}UkEBL5Dw(C9o@iG7cj`1@~$l%2OStGgmp5%Hw>YDZPEQKbC!Oh)>i=} z9=Dr@6U*d*Q+MtQTNtY$iVN&RpjAU%75{Y$H80opLwm!A+aKpJJR5v_kc|~xUdD=9 zG&}aTywXMN(Kp&8%^)4HPrJBr8jAi$=K8og5w6%E$RT0@Kur>AL&hRvqBpR;D;LuE z8|@(%W2T9_k=2<=yE5dLp~soX&XPAVZXHwusN|ROj;f&*3YLlwAmojbc2(L{Q{pXx zqfw`!+Of9=3Z9y(4`$?7arQ;H3oztYNwB~BVL!F` z;e1s1t7@R_z`*KQ?MyLdP_TK@Txd}+EiF8dz!0rG;)2LV-oy>+i8Uvd6R)X>1YI5v zIBph2zdHR09UqPvUfB%sF>3FY@z*9@ z@WB7rrOn;~F@@4NhUAF_Gr0+af(5MlXvffyhV6pfz}0<-xD(pc{F^pfhMsb|^_9f&t0yy801&)az0 zct+_RoPS4@$txLYS8FLNDHl;$Tb)2^y{!;Pj3mY}^z=bsB!_wyHM#^L!qm9tH^ber zK1P8qG889O^!J4(jTo;i>smc@a?uj)mP*e4s=J)9>VZ(!DV%HTac+1RZ|@%JCUlax zs!l;~l|#A*35c74eP>SmTPjdSP3C`URUG`aesk+Bf!ML#<}Eh_m@A$A_C7SyX)SeB zLsBHQRNvjaTR)||L|E*n^DVU=R2G_{+F2ZJR(K|N{O&@{(MI?h zl~+RZrtkt?!sx4eyo4dF5qRMEDPV_j%L+6ms!Z{kse}?ZabMyfxHn)Qg=1TUuQ7No!;cL=;w=+q`v6_T`)rz511J;IOgeD(&n#W94F0L;j!? zQSUN-woZND$8f#ei^RoTt-pg&3u=$5Qd7v0ar8UWFO*~cdMh({9j`mxT=D3w)* zL?$nLy+KWU>&A0DlCz0peg=DbnSIyzh%WLlkijehwPB1VE&g2EASG_vJ{+$btF4Ii zYT|t&N#Gjto5f6ogXIn79E#e_HpP&OE|HFJ77~Xp7}>1wiuOkr$(8nO$vA==C=y=% zt7G`4!M%rdjvJEP2J8kQMF-}jEW!;z4th_Pqcv{_rh7Ac5?dfv zzw+WCg2IGg@gd; z4e(CB&DZE>DwNS<|47yugJg5TC_H>SSf&6s+UwS+6TTvPsa2vZqK^ew{FlF2W4=Oe z?E`(gm$M-J57Fdb&cJ`5Nk^n5luwb^f*7X6At-nQ>>udW()@Zbx`N>mIPJQA#8|+N z82dHcYN>Yl2q9)^1=4BxoK~$@W~+|k8U#pmK60zyxU%SbP$uhQ>eF)Sgq@r8q(gQ} zKpPh16z?hRs`FdN?yB=o)%z$Gtu{zCOcmHppQzw7`XneFX7`ZbaW|>j3$m97L-6;X zUy2v0*W{)Jo+pad|3=uIT&R_{?pXp{XJAgx9cHSyIf_}w3)YG7P=u!v_vi?=&Enl1RaUK7bi6O=67Y&EX`@m}HWcF9u=?C=ap~Q&IuVfiaPLan_O3MEQYToRHZv z8XpIL>SjeG70PM{Bi@XVGAnemt0rV~^C(ioQNxRpIjl{!r&d`1?9v*uP@-nIRo?wo zlS8LxbTB|Z>X)&(zdkiEI_3o1$v2lst1Y{I!-Do&@Wd(OkvvIfQj~T{M%6webD59V zi6Fq$qpy2J(Rj81#;DSv+uin?JgKaALTkK&1euCygKRoe9Zz?>4> zQiQg{r5HdqxUPZfM-$Z|V(;53%hRZ+KQDe_-jM;@K9i|-u8d&|NF#S46!8OEzWYdNTFhX;FldLlPSm^O?D6-@oU4qewS zct8);k4m3vmnu*Vx{j@Pmn;l8%z!Ggj?D)MlA;Q3#AT4_q=e0Ph&lXQ%^~Xs4TSn@ zD0nU!IO1Y>-K6M8#|dlxsB9tj+CGA+0{3oHvr$bC(-RqmPeIrOIL$^YmK2crFn%g` znloAP7oMVE*4E}capDE+-Fv#U?a36Z==?_g@D#$sSb7$fc@6!ivgT5AbrWg^Lg^Xu zrD$Izk@1`i2Vwq%!u?6Tf#}-HFV7qn_SC(Lu*vwqv=j*Be0l*{%|UIllFbq9fOdzN zXq!_+tF)7>YFM)6sMW?_mq6at8v0TF+94i@a1!T9Y(HzJ^j!>6byg(8dSZ17=!W zXA%}}Ba3&bg++e=E6jRgy%<^*k1lcf)mmI<*ZN;ZMtd zryB#kp|M+<+Uxpl**KwhQW{q|Y2jq_tt6K;mtSTwIf%sbS>B%pmk}}LyrR5YD(8}zOP62y3qmi}au4w_ zuBKOAv>GN+ctX2s^Ru=dSKw0&A{2*2bw%{gn5s-J5Ns{ zcw>FJRJD=s#?BLz3gz-GA73>`k4kZ=?t||}$=gG(`A&G-y|=cS4)L?O)`FmK6+$~d z+^JsA5@e?g+)3*88Hmk%pIghev@h#fDlUS%-?q)n*aKt_D`cm5)N$*!e9zS)<-J4? zD^#cO(gQ_L6J)1!)qEMq7R@tkheQ>^J8qBj>B4L9b{p_k#nN%%HuY<4lGxrv9!Fw! zuMVPQ{6P&>;`Na{mL%|PaTxJD*Qo(Sh7u)&SW~EXyal+gYdLW?U~T5lbWtRq#34}M zTP_wvq1#}@Z(H3Iz9|Drek0s9h|=5UAn#RUG=6DZ>KZe$q?y#_VD35aNnIP8y9Jf2 zOcWJO}vg5QeyJ-_fCfF9HHEPe&|~LJW}4?Z7qaaI_|MQ9sj0+w^1A|V2lOwe zZ>7IyJ|NU}iE!t0BY{uvd%~y2x&)d|17` z`R{cGFWQIEJtDAA(UUto#uM_W%gLZRx`SlRo#$N+Tfd_c&^9vI^-Q)FDp(eq*O7tI z#>_B*X?T35h(>4Q@|*y|;G#=11m_#Qx;gTU@Tcm!)#Q2#MN%YiqR~cIUk{*eeSY$UrQFsmHawD? zNL47m9+i9nz=`vBh%Z1&5FxaKFji0+;&37E!j004xtd2`KrJ`I~#koB($#O(S~{|^25ZT$3RatE>vSwt?Q5Dp=3 z+vMgc$~JYoQtCn*PhDD&%3IM4jU<4%?ugTjFQop-M%>@CaV?s))RSgT{(c;_ROp7k zzf$g4HJaAiST1p-&U`NYU0{+r?XCMxyC&>bkRBronWg^%jC|_;W|BgGKqA zviaJuH}*(0@_d0yl>rY9RF5L+&n@I_8lFFg{FZ^MyL#-Fa0unREW$1prcksL)1r$W59AdWq@hNBfK@Zd?Z zy|kxWt|RWFmiD(PFRynHT{O>!JPZR&N8VAo%RW@1_hQjmsJbA7n-}?jbnkp%#w%g|-=V&aGQTJP&{LynP20+khhlC%=E+lG z-bCVE?Q++6==2fuvKVOgfz^J>^@&1qy$DQB&q1EjFy}Tg$7S9iuzHI zRifv+Jd8DQhu_v`_(cIyCs8$|i8 zk{(2dJM4bB0_bdy0d)2*0p9PV0d#(wx+J2+4#m0%fU{TZg65@ROx&lT|AaUn>E5ko)R!F=0N~wg4b=Hz ziY82}kN39ONR2wKbf23Nfr}XeLv<@R{V0WkzpsH}=@B}o?*M`_MyY3Kh;~=3^|Dg) z=HszeRYcz2%Kq+RR&xqNnZj!(ak5aZ^x%$|n&|WbsnR|Y$51ZrqgVDIp@BK5ZYKG5 zvxmF3ks)SuTVRas*1rnM!ILnSo|M^G(_i)k;UAdqCE5l&6-Rb>iy<;9o3NqSYJ}m= z%Q6YoAjT%YIq2b4Z0(>mwvLhJh(uo^a-dOGrgcr7Q-G7 z(=^`egm!9Wour2~bhN#D90XP-7Xpy08F1b~VL1f*R;D8SoB^Dm&dD2NRBv*|zBK%6 z@;wHlnUb4v+L|W&&w1Pei+Q$TK!;1ur_oI!d^}6DI1YN$JM5KHda9odo5D%fKxyaV zA_j1&y!E&)a}mn-4wJu_v5LyXloh^kjA+Z%ZxyMymWf)3(psI0WA4gnw}DmetEemP zL~9rS&8%v3D-t2i&R0Q`w!VZq??hDJ=)3vkDhTQ_h>|z9J0q5_lTB#-4B37lz z8n*gJ@`v5pAYAO6J22+?GAkpYUOE0(_C#}pTa%r0TLnX}Cn)FMKGtKGe^R1L@}eKbf-RWDWx$eKi5_^ z5SODv&*W?3uQzu^asm;?cd2yj8_!Yxi<|r3?xKGHbP8I3lkMQHvr_-nSTEN)3x|ws zXcn{3&l&;8919;NO@>d;CEbLCZt9$NQ5oztY=Rgdgyiugig6{CcB`A0e`0u<;qcv3 z-28ZWTZ03bx}ox8TAWQD=!3@9+vpDr8N$e~F3}(APYg*7;SeMUCIoGB9ptrD1+}J( z1ht!w6zF-QMK{)#&=ILZmzZ=MUPKVQb(%(jZYjJUXlvd=*ulTLC#zeA=Gx@k%~85x zO9_`bh}Nq+0r6ms_v4ps)`o|4CIerJ%Mx0`iD@eElEFo6Un^iJ%Be@EMJ7`)87lL8Q6<#6<9m@*zC27+wV#Arhi*3mRY(>(KndkW<0z#+rVMcn}<^I zm8aCejjc?Ay|6o5uO)wkmZJnD!SM&Oforp5k(~?14~m)c7y07xoVZ`1pjYwdiPSWA zm@9_^@{U(M_U4##wZ=j64RrN{grILsgRqTq6hvcf$6sR?5A+jeGh=T-9SWoq} z-13bz;fQt#C)T|#7P+yDETwan^HqAABO)R8%A<+mjRGtxpB4rnPhX8Ue6n^Ae{qiq zI=t!<{oY;F--zd5sFMB-5&nPTF#p#PrXb$JW=;it=&PuOO?-o;{(u2JZyJD_jsZQ% zN;7U-Kw&6w*{p;Qv(iAGaVaw0KcpkI-osn`9O$P{eUoOPSt`7MuWGx1KA!IEBVhFQ zL;Vp1^&<&WboB1lR+mHM)WT$3m)9SFZ2(mJWuFZ7@*$0XqJ2I@g3K!rgGM% z$^E&z&S*FT*vHP;e*mGC{z%DdJbJZ$YUa~7ca!<44)IHgJ-4+p?;#N_W4a!dn*u`_ zXzli}eA-Bd9Gjsv@dE{B(fL<8-z2zO&c%4MCap!y)Yh@T#vlt>)?P_jvS5J7d?W5u)iR%pA;K%}6>f!_(sjG+t(_<4m80A1*66323pAo5i@>WmxVFqiur8cm?e}yL*W)un`OgLtNN})`WsUb|FsZkBMhEdE(D+U)q z%XKkubw>nvdU)YnQ#7KTfgWVH@{c>iL(8HBcqUV#orxaO`)A9dZ=PUz!}{rsOu}g# z;$G6^=l!18`CR^p9?Rrp_uQEABs4vRmN^lyMrd2RoTFDaK$VK0!C1}Wu24;OQMV>s z{e+`KE}^x_8)?m|JShl2gTEb(EdnfaH5 zkq?P2g+E}XH_@0b8$Z?J$mB?BGF;Ltu_p| zpUS^yY!#{yE=sB>pEj{0X({d1AmGykIZ}GDKG5Jw_)JXr10=>hByv8pk4CrPv{Hu! zHs2LH{fb{2rH%y@ztHNRBZ_-1BX7h4w_E*mQ=OtoxJ^v~FzI#R}^i~}*&+*__P z|7>-9c}=z)W&AnZIl5}Y>!!$guEBMFu?6Hg9}>Nm_gt^oHt=NH!v(=R`b2`{IT z*}q9bc3+9&a2M`T{a^#rQM``E19aEw>GPx-WJPw5Tk?|ZX=?e3^wntos`M2_cAtu( zyVTd{oQmU>yB6eC*%jq_uEC4iB~>=CIz* z@@r^wjkk7o78>{7Ueu58Q2%m_Z>)m*4QuwN-c~6LCh*T|(0%ZRk`8z+D=`CGj>g z&17N5ul2=>j=q`eXw(%PR)ZbDiN)85Wxi%Vk&XKJMy1r);19+S&Ft2t!Vay~;QHv^ zFs4gpP=i!%a|C%SnurkwpA$>fpuV*|hI8;taaxtFftb?-I-L;_@CL`&~pUuRM%pin7UV9IMnMKXo9ri|DqD|igGil;E`LLz`(GqVq70_BwG zyEmN_nd$MyF>`AivhCkN*$=&6)x1XfWjR~UhGm8PE~OEXY#hOEkv4m+>6}z-GZwZNJ8DCY zo5yrOA*vaLyq?J4?IYjLqTu0b)D*d*>F)2hrXe{ee-9OJWmE9HTY)I2*By4>5&!!8 zrf!zyMbH!Bg*Bm?#As$djbbgH5bVqHjB4Z|9;n&!HjPeHlm&332- zV3q*6r~XlvdXWs_q_sjmkZafw%K=71<(WoXBXH-T=H}B=YMzSFmZ`00$p{q;mTO0- zily8Q*1Jm2mC`$|m)wmg7k`52ZxJ~=>P@2R^87aK0TnqBo#@99k-XPz)B?AuMcQ?& z8Bxo={B~a2+=25}tzVWuOP5-*ojz{!bWyU9)f5aXN_J)03iQ$aIYe_ss4|96*!ct`Rn3et}E#N?zx;2wdap_sg3_ZG58nl1% zRld_7#Epwr)be3%i#vb9n;ksI>+6GCO&5*N`i!X60B0~d5zFV02)h>yG(wi45@#u!X z#=x5qjwFHVkdxa4rUDKO)S-&;+Ys&JP|pfzauC1rGU-+UsNGeM=`5Ryq& zIB6(YG29;i@LroRlghFEmqdPpm8RMNtBCZ(p|9VcB@(w5`Q68pKPMaGx|19o=6w1s zf7+GuT5@S6PMd32uS_psx!uWQ*`a3NbB72>UUcbXa4~TUX|tUMT>E*lMfan=#dElN zAvhH)luj#X-M36M=`%f#d`rM3gsQM-spV?mC)D6R(;#|EQZucX%yYEmuFTjV?fm`i zHN~bR*x7NgPD(hSt|>HyJpK$yfj#`F5+NN$uPhIEOq!cFddj78gg$^!V%ikkvu=S+ z=C@*O82dinZLzC7=1Yog39AP4nfbq0)n&E_`mxOc&BsbAau!EjU~<5=#k1|xL5Kmb zo*|waC$I5@7sN9akcwq=Lm4>}ObVDHh&?wNn0!uxvRUMK34K!SPEA_()FH+Xzdcbi z)%@2G7e|iIsc}*tZf<0ynsn_bKvJFy>tgJ?DegjzpZXtv&oeOak z#!`-^Ws0D263ONG;hFwJrTS^hSe>~YY6L0~-MpMv&gM0})WQ=*^DNE*qvZoG=R)pZ90F0|C zQ*;I|)qW<{F?XCHxFCBt{qZZGUE?-6&%gxG0W`#~@`-@G@n8qN_wom}{BCw`nONl5 zoozBYdAA+0ot%2&puDy>VQf&}pebM^cRzoFcFb?+!yWX#1rRoEQEVkXR5MW~xFIZC zX~0NUL@?!Z;Z^$BpuGtfNx;Z63g9HG617f1uFWg^-v~f^oD=fIrwaG6G3{NgJHRT|FgOFHz$zw47m|dfG6>3h#_O^CN*Vl)loK0? zw>nX0ygEP|QAc(nQv@w65&cO7H#?71V6O}~Vh&(-L6Y_%X(sX0b`tx;h0QckeYK1c zv7<~9B89GC;!3xzhMaNoXusUBtEl>fPsZPC>^{GI1cA*^je*V1}E zaAPm~|7cyx7j5!QK$Pd0YOXE7=W5i3thPer6%7-Efgh8^+Q=vtkQ7Knl!c-x=a0TI zD3yqpD8%KAzKOr`Q8XQ?9=uyBTa%{x5pCVXmdwhcM>?Y8#eW19*Y6?0H+v_^-hKWh z$@4|810owT-j&|1*~8U&NXiS${iC82qO-s-MGo6BMLv=J?<}u!`(5S|OMa-kyNHE>yvH7Nsv5Ygd3L)$+;uL0t+?}Cb*dh(?#$Q<8g4-uB^aj8p*Fc>$l-1OC8jf@b%SK^8EN^i;too5zbN7x4mgowRb zM}gUQBVm*RfocraCF>Qrh6<#SM=W_P@}hd$PrLEE?a@WJr)qsA!3G-9?tG3QWbMa} zX)k(_Imu<1*+#xtSoaC62u%z+&08^5TN!{kAxUFV*GsQg*MxC{9(}=%%e}R!1rEOF zDwXzod_DsB9@#V;THBluB6kykW z_#UxrH2N@=q``o1K6z|Cd1M!RW5NTYFjH(ky)-@Fc(9s@%{s>kd!ic`Ufp?^m~1{} zjD&c>;Q`U%eYsS_taT*&MT0TYZwKJ%T?#j2>>onHNeR8cC4$kPZ*R)LRrb?dUOaA7 zXijukG&@&-E$z7BZgzKIaW_M--hJ!hY>ZA=t*=i`;H-fYWr4R#E*xca7%z941pZq89;-t4M#4douW9)h6Imb!@ZkHqS- znNlmt?U!xkXS*2X56RKBa-*{>4uH18)Ja~!&PW;kA<7P7IWdkNDjCr) zexBIg)*ZeEBPiTy`VE6A|Mh5VXtIn~AWmqR!k=me3rtW`y?_v+7KRcp5<#gi!p4{H zrt?7u&MGcPh2Hp%wbr}XE)r{&SQ3=i5xA10LG*ArFNoiF3VnG9=*l#na4zICgg)(; zv*1>*!!M`}_F=eZ($^9JH6rMWIFe;4EVZ;dSO`L-()JK-?WH8Gt$qhk6$`uxNQk-c z7S23K1ETE8Oeqj!tq^}NbUfC(FDYwX?2GZ@K|HbgYdOR0en6nrtj*%OW&Jm7WG;?d zFjostamvfKy2hmA(x7#ZJ9cHyNL|^4Ng4;8h)N6l(y2S$8xaO`#kJkrZ6$?Ay;PYK z25_o)2^v#`sl)hbQ=Av25%-12Xz|&ot;Tmzd!jyHUpnuzG!8;prmq3RXKXJre3&B7 zPL-~jJ0&Una#UgsGIb?A!}#E&BwuW<4pq^-z>dfHz}KK)Q`w(XuzHfZp2}Q}TBHgW zN?qw|l#`mf+M|LenIdd+QfwR=y@DTC$#A}XW$hlPHT0XXtt zr{xKi)y5zy)S2nL&+~H)5ar6;1@7wZXXS2opy0DNSdcRI%r$=G?RIitl&#Xh5GGHL zUFM5Yp9x##uEX!R>1&WqLsp32ak{J!k1@KxeN!NeiP7V9MSKtD-2;RvWK5qiw@jZ= zzp4G1OSeFtN;h$VSvOFeZwW75c6V)o+DztZzQV{cm8AipyiD&QT`r2B#ztwru3vj9 zb~&e~tS}uz$7ZZi-drdT81=&qeIF2uf74njs%K?%?Koq!-sNyE z$bgg)3Bb@EQwWn*hx1r-8>$**;0k!#ny^3V%^sgB(REFdf^?RY!OH9{Gx(JQ6@m*z zISYqGdL=%Wqg?r0)2J|`jCFGUJqbHN@=%N6-A($%Xf0=}FbUmi|P)HvfP`bC;X3+uaybe<#y9SD;5HqBD2dJeaT5DX@@oSx7lQ zycxZThSJMWSKJT_voI66uSoQQC|`VCmWa@x0&J!{(8=PNY`RhvOAzYesdY4xGw&JO zI5?3YL;SF>QNW=SBc+}pXGmKyhvy}VudGkvsf=|zYU_4w0@DR7I%lj5g`XDZ|I z^Kteu82`B1R+;V(9HlopsMqS7&hV3cT8Umgjt|fbpifn>fXjCg^P?G4KoL1OGAlNK zgP$VjMW5iW(y%TkUb@gqO1U9!zh)zmP3FEJQT63RXOer!Li1d7QswohqL3brf?s2N zJ==?Qs7@t;KY-=Cgyze9KbhpakjH>M%&;>xKZNAFu#X_!Y_N@5Ugv~87*)XCs3UJR zKZxYJ5UG7Vm9X<19^!;QDCBkUkBfp|Rnke1hx+AH%6J9mt56>dKt7a$o~5KX0-|8E0C%rLB6+`_Gqq16)I>$#;{= zDp9$d2xAOI=BeS0 zUQah6M_QSSB@@l}OzrzU0Gha813l+pKLHFt`y;04Inca)89kk^yno)^p?Sl!hZ_Js zp=gRwL<&=p%T;3!LC)&OBN!_um(#%+a>dsS!mlw<^{wee&!#{M-Y017L65}h-E%a^V?P0(Y)#91h>?W8W5+p4}9u4GY96bM_p zM)Fe*a5S0UKdnoH7F1>}NAApk_9<{M3Lz9quF|66h}uBJY>LvAYm${-mzr?4xceBM zIFgCl0ne6LD{$fWjG_5V^`R~+72hKcwQAfOi7B%mS9U((B-YxnW>9=<9U{bjy)Vh! zD{2K6>f=Ny6%UWNl+SJqmyvCUgcs=_r6hBy)`U>&H7cKPg9v`h$_z*2kW$>NA~#E>a}t=S8ju)*?)rs7pjt0j;v_b$81JARfz>!d`1 zvRZgNY0>9-=M!Gix8uN44s&a&<_l=5m?z2GoWG?9HM24_11?p6kTR#n-vw1KPfxtk ztdj?x%ZI#%>)8?AMO;44@?_goJkN(_L5ox*{^S&|`$53;gG8mv?}KkYd=P)_a8E#s~oRFnB3p=N4by}g z)e`G=1wgkHDEW%x0YKjoX30z^-<}YF7{Od0o|zlbsm`x8V68`epbIwI7^tolsW|D! zy@Std8&1`qzcS|X@5dS(fdK$kzlr$&72D_UsoCF?tiK`C|BEaIO^pox-MAtl@q4CI z8F}bS(3|cA07L^)i^@pH|0j%m8#!V$nIuZ+ucheq-gvs46n}w@C)z!zGbndlooB#z zIi5^L^<-F+SO{9!BkjpA=c)Ar?9Y#@D=&cl>$J$G8hCy@L=My%WPaLBJ)0D1g`qZ= zs3R4Z=28QgGp_cj&9`%pYy+UQbMEPy0JxR6;Et%3Kf{MeELpWL;S)!C?g)cPn7^)) z6V;oG@R?XT3vyiXljJcuRHY;bbn3yBaQUtJ0&yDQKU>~uN6h#)Z8$-R+AqnFjWZL^UqSO zrx!e|Sw7?!mos??3biDj54$YRoj@shPOQXxL-iZf^A$lUDV!aets*gt--oo#7%|j2 z*a-w!85yZ4ied(uj~+fb2$yyHDsfCy2F|SdDyT8=r#e)+vv+xOj;NA2CXdc4_&o8T zr~i)G@u{ASlwIuYtS%Ub!7kTpRa=BJU*TH%Q-MZc81lp>50`fGxLrTk9dG9?`g;9iA0EKDt9VD#?=TJyNN%&Sz z5>Dk>q}xMT3x!l!bT4Gcr@UN~SA8b&VXlu~%HXcsc&M*`axjUis~lxtgZu>u!ePfVq-LmDWs#CUY+qP}nwr$(C zU3JQ~PT96?yQ|-QucPmc=;-+V?X`c+xgyt`nPZF`x#i*(c`5dXRlvMm;%?Q_vz<;< z^?pNMDPP6=-pN-PDA>DDVP{N6Ll=+)T7YcfV67fn0 zor4U;f_kre1lnnFt#=IBGB0rp)};``ykL}X1h>lbP1kLj9QY!)mH+$j$=}x_Ummhk z;E5u7&x`=pEb|3%P1npr#s{$`K6=Ksmk;gIZS^*bO-q#bb195X&Sat;EgzBTTgSMO z<378>$ty)t0{MeFV)@|O z9f2T`D);Fuw@*+ZEU;M?m;onWjbM=nV}Vc$Sq7F*<0c>2UB-&FkQBy1v>=DQz+?kn zMwd_HAwSSvwhm(f;`&<&G~c7M3|@CZ8x(nf8(>koOj2i|jP^_#^f3jI_xnF?;Ky>U z1?`_3nDYNI@a6w?hzS|n**cm#$^EDpot@02{#);vt)!_qF9-J}qnKGT=pcXN!_T)? z@S9TUfMp&&{Zxv2Dy%c~0Bn}!^dMlb76JDx3ij)lZ_<8FV{=+F+~mM$&ZN)wtIM>F z&)3@*P%lF>(#F6iln7n*4uA>6Up*BnM+h7P9W{3S!(ipOI=p>&L5qQUYTroyvBPKd z1X`>_#wZo)%;kV#0N3Y-Kn{13ikST6XXj;v_ZY@gTy>lQjYT_*3`^!r=Nj~wapv!$ zQSQsYORq-e*sP5w?MSZm&QrIP@3ljZ9bDyCjz9tWjq2c$Bga=Bin_*A!11T17UXqW zYQ&njNOX$1gqTN;0WT{Dbyg_SKi>UWl;s;Rl~$2LLJ~2S-X%f~$KmJxL5*!`59zEj zI~ZOg2*J5gC=Rz>K2_sxRR-`G5Xh1YIb~#fj$~5>W4@8uDS{LLHgtnPi#%9*%W37G-hsV={MX2CV#)E{qt8;yCcQQ zQYb%{9q}nTE7d*)tN*N@pRRTnZmDbwjR)jqRzwhXx1j4}@T&&U_SZkuHF|_Xjg|r9ywkrf>-8EUV(Z5tdX{l??9>S)& zGO|aF>`>nr*wYc&7}@hdfpxpZ!!fwjM~QVK&l6Smj2hb4fw%-;f^oM)ldXS30)1t& zoc`mMGUP~=a}3_yyB0~MV{lvlBbGtBh4*n+?z4o@am_yi~N*Va&-DQe{sVX^>O844~*X!Pz=%k_m0Pg!Ew z!xjOs41si%2uKMQm~|V3sv;7KM&Bqz#|#9jL$)9IktqO-2QmfFcOfChKmMkyq*ag3mwLXIm2wl0!9;FcA)=y1bt)y#7zM4D- zsGG8HFq_uhfw0FgH)RqVPTB~!sX4Mr7vlr2GUan^9`%<+(PskjFf_r62ksiJ#&OIv z6+I#4EX=kYO^nuihvM}8{EDh272q#soSc`fD{_vZMbubhDp-dKd8&eaDvbo4u4Ig? zSu)gKt-?l}pO`RGvEU56{UfeeMPm6hxsDx;iEo{3vsj8>T@=PTETNfEOrjeNXA z4QyNK1{z4QHRMULWqJt&MIlzk7P4>kCD#XzOnM97<5jhj6d`*<-s4rW=eX3ZcS{^u zd&B%~r_skMm8o<~-EFu=G*6PwII1OnB*wrsdP6jj2t|6!?ITwQNU5w9R1EQhv>^JZ z)ImuqTaB?Ia*G@a#nYi^(|4MD0dF!FzBvxbB3SH`uWLyK67PaL6aqchVL0p2h=wjmYvZY$? z3QapW&$GC(-n^hHbPCm zv&=a@dx&9d1Ir%T>rXNmSOs6fE&Y8#hM_W6tF(F2tlXj3Y93tvJ87-_fvUV^Id!#6 ziuV#*0{|3Dw>(P+Fx%898E3r&U0#BN8(Ay4nHC3XK5K-<$&U6Zw0!M_^Pq@jJ59#d9wm_X(axTe&>g3%DL;To&uzZL4qI>t z?-ZFWw`POL~?nVM|;Qn@B$cs}2+)Wm6%j?4pUe*;6;Ad`3Mr9r=|5K^l& zt3|pc1omnOgN<;@^?Qzd!FFjGbFyk8_a}eI_Q0CIqco9(3AJzxig1uZWz!Ij(ecE= zUTQ145_v%nl^b9JpWuQjz5}D!YIFvqY$^4Fv(CAMge?2+ImbI_Hs^jB|7ASz*`s zW%DtS%Lpi)e9^=Y8)M#1lq!N7%EKm0+e}4mr_!Z}Db6fLE7t8VNO&s8Sg-?gL)31V zkvy`bw^QcPR-F(aTW|&nerq%s$`-K)tVt3#rC6Ln^H7}amu*Rx3M6B@4$s(oGaGGM zSI^~q|A%JGzUU&o^XD!tLH+;Jb^muIE9_|KVC(uX2&P!|RTc4P#5@Qfy?$>5bYv@@ zo^c`>*%GucV1V$SnriJ(BfnX?zEPo}tM~48VM|L_YfH^0>&DM~U%u~>oSZFAMt}TH zq5<;b8;9-j&u-6c@8`|;yXPL?FJL{!FR&l30Y!)q=a?V70KgDH2;NZK*gUHk{L3YQ zm^v(xZAc-jxE#-k2rzBfT!%4$h}hi%B(5J_hZD1xed3Q3k00p`k)&+h0~74@%?(v8 z_sCL?=_xRd&cQA*j?U9QGOtduT)W~tbAzaWz2i7Ncz3suRPrAuwfV*Pg@rT=EcxNR zMg{h)Fp68li2U0P^@sFC4Tb*UT{8m;E3^4|duA+YG>et2bd|(iMUTBI9GSU-ip&rZ z%FofVc(x8f0d)mt!n4+dh)f|lpB1HoQW&y%7~3$r3iw$lW($(2bbRiT97XZkTJ~Dv zd##tS{1b6v3kz^>(eWGc!zcuqbPcWzOSG|xKPgP3Pj_hK1|JDK%M6?lhc|T=KCR&s;FC7+dZnt{o-Qx9 z89}}J)&Wns3}JR>-y=@&N5sENPbQiIBlM@##9agW^Mwk-lVt3*wl@+&E0E~)p*qA`eH7!zTIbvFlp*}dEt{#Nh6BhbSGkLck#m8`mm7O`T1$ov#X%W*5gn@1 z5@H~2X)gI?6jTlst~qCY&64Qm$s=~fWTMvl39j@M{dtVAX*V-pry;=$aV$fhNd?@g z25d$ghVSqD&t1CS6{-de9_GxNHC?r4N&5>8Nk=))g)q1;vNW8otsY-1#|BD*CDBVp(ldO;ALxlVBL2QM~TbA_dL&USA&}#8XDj~S|F16)kOEX zna)Mv#d{N$G~;XvPe?|E)npChc>IlT3K1rWMw@XoW+ZYEdNi?O$Ret*&opfd)4se> z<)xj7&69Kl*d<$bWDUU`Q8hP|$?8OKE965kg5)BZ)lTabuUE`l=;kmqid^B^20?0P z6JmKXHP&qi?Rr_%=QBiZV8%q&SmTJc`Q0&)N7ilQa;6#9_@)@`$$<;AOpuY{;DQT6 zSQJEap^JuK8WViNnEF@5T>eJvLr7-Mi0333Ft`6n?_Awuv#PbDTd&3w|IX`+t!`b0 zIA(b(Ma@C1(I-8?Dl9hN81gBtyFmEpuDn6k&5c$lFJ3x|kZ7W$ASQ#jj5l*9bzz^# zt{E^o!fXgNS9Au0trrceMcNq<_^`Qv-$^aCcV+P@gxikn0`ww_uCV$b!S9BJ2k7RA z&am<-h1;ebT!y&O7WnXk>k;tVrW(9P+&lmMLM_1ci2=8B`cyqJ>US1uOg#t$w<+9TAbNJ{&6qQ zk3vZ4aaD=aL1EKY{&6SHuOgvr$wcvTLfmRmt3g8O^pUEBM?V4=bx#n` zODN2jFN_v`=V!5?!7myBK73)k_=B}@JI~;^u;91OfFF5q-+zi9|N8!WWmz~r8x{5g ziIDu5to#$EU&Pp0(b&n!+{X03S&8bTA2fvT2i=v-%O~a|2ivN}qbBQ{TY_XQCuE#Z z!fEXab?IAVxg;Wo@u9fQpL*E=y%A*3k=86_k;KHhx2yMb`0Cl@HkJJ^ID`-6l?-P` z9|{CVm_D)%P2@%`=BQX)B)&i3fm-5TD5I1k#VHLco>?E#HjrPkBnAy+TS+oYzZ1`@ zTeB9+@wk_RCXrOW45j)m{t%4amL0U~x!?FNO2lHsX_!X!#H7LEZi%bTe$DG_jZeLF z>JK7<#h+t6_1tz0{=T4XoM!g|?%Jw-aKKw+4M&+Q1#C9Q6z;75qv4LZtS%Dg-Lp&O zH082wYfN{uY&Jy2*2zake=vL#xR_bd3i$&$8kf(Yzm~3SlJ-4q$B`2h+W%G_cBy&} zb146}evosn^P!KU!HEjfEu_(3zUt&J+Ft_G9d;cwH*(S1xcNE@J?QhfE`2@3+Tv9M zwb#%+2C64TWVh2KPFr!$sXrUo(#c3F>Rw00{mYa#rY`{TCxe*5AT(xNer&5~UB!#y?EHj<=%K$!PABPtEvZG?1M`{bUJhXi_uiq4 zeKg8(6;4Ex-_VPB3T9%-AD8U~^OrHvu9jkT3wl=PY6b5dk(1wsKnhT`{lIbQHlZv4 z4o*;P=3UdrI3bcm%G7>liIShy#Ac`zgeaAb@|2+yQxphDKk{$h?_Ym|{Cjv)x{dIE z`~W7~Kl-eH!nuiy={w50{^-5_JGzVG`y_zq;X+88T$(66Zm}Qs_~dCR1?s{eA-St) z;r3@rY!ZzV7OyJZZvec=?B{T}!UEC;;=V&)za|bo_aC8uP3__Zc0oNMW4)t_a@9$Z zcw9j|i%~*A*vLrir~Yj=w-DG*r*nY@_Hvl>w-0`<(w-sFxW1cr$j@bNo?T)yS<*Ha zoIt)%aXE6bN=KslmhF5K5i=G{Kc^evBrl8{|Inysw2rdXR+9Uqe?5-71yPp@;;r%; z53#YP9>7LH;Fhk0GCkde5a|&Hp&u1)-t%&%VAFurwqzYR9T4a?%H!jQojZL*w&K@) za8aOx%kGQWFrKzFeF6XXH_BdP>wNq}1kFSJ`o;GTpeS)0BV#vXqyNkF_J2}oP1PS( z=nDoM3LHpnta?S_&w_wh8U!$MoJ8BoLXerDdEa>)dyv0Ai3|yK`7)_*0PGilZXImC zDnI^T=aEdYsm8;9cr)k1gJeS zBmk9xIMj9IAvgVCKx=GT5G>JPpc#Jw`uJWtlCBS#2`(`FAW)qYa9uzsf=b|tkboKv z__$%67UKBhFP>pigQxPKX(BJ0UC59U^v#8A^^ovzFD;p;rr>p_vbB zZL(88OzA%5^oDy3u}usk1TzOgTn@b*%x@jCeR4j=7**o2D0^Dh&UF0@@nJ0kXZ4A40c^ma14zwX+A`iA`f)N*$2kFxXb|pYfS%n@zdNC%Au2Ld%qF}re0wuu>brE7}zGQ;Gf1vuG2()vK!Q-&HZ^feh5&yWLm z>(^HMtYsaG4A)8(ep>MAowi#~Zp>>fuZohz1**0>=?ksRH-;>y#G4|_>n^p7$`7_O zRXg;TvKr*k-0DpXRa@&VUcR2a8h;x0&n&9~(k4d?P&4L8kheHyE{9)FkdqiU9MSyC z9^la@z0MiVshxCTn0}m|K&;?_;VlB_=k#7oKs7a z-9SF53$Zwj`KdhKHW+Qce=ONuKGkW_%Ue<#KE(KWJY?ijj)V?mg+#yj#>L?M2dB~4 zgzPTis4YR`I5i^8AW>&!VhMEEdyBUT-$kL`%pmgum=x#%m10x?uL)rG8|nLqlq4J) zcfp0|C6F-eBma^q!SvDih4jo4@1~SpWug%_?7RR0|1=Ht4_592(~!cH|LG`APL%xLn&FY}OcMKj4kl{<8y^s{xzO;S z-wKryWPs%gX0XD-dq=J7Mv)De)!Dyt0mC6t2T6Za!?1k-_D6#F!>gKau83oX?+}4s{=bn0G6>^yYc=@w{F9EogslmfysV|K*pPZ`moj~f@1WD zNkZG5wokF&S1tyddVg&o$P1`L6pS+jopbRw&S_=PhB;&cpo(Y)KfCYo&&sP zBi*vm=H*3$oZgy~v{(UYq1dUJ|+#0_Z!4R$=|G|&_+?R4X(?(pI!~&D~&PVJ)}s2am9J%^5ZT^xz5UfKr7W8|NI)^ z$3ex)>Qe_L)-qDdJkxE zbJ2VO5kU4o_V)*&_mv#H`YuoeMbGaqU`~Jc3mt3SO`!4-UJ!JF1KFvu$ zt=+vc>V$u-{q;GG8(_}CuHuH5pr37fFR-cm4byXueQ(2uw~U`{TOQgJhxwuVRadWP z_hc8U`xPhDvv$sV4x~=Nwd1w%)n_j-ZxHV7SuC*I5OBjz)i2)NYgzY0QyR07T+Ut8 z8_BJE%HcQWXPuq4?VFpH*Bgot8Ncn0JdCeiOJAcgUi*7foUbA9pXuKA*Vh~Gp@?7L z-+Q|~ZO<8rGB2>Ox~>Sk--lb6P+z=PU87wsW&ArJZKM0c{n5#on3sYbet^E%8*Jja zCwn?Sp2-By5Uu1$fBphjt4#!oZzRPL*fFpwO8mOX^5Q}@Wi!_=@oV^<6^-Ws2*AE^ zkV*j09w66AO7fa~abz&zL(+UdMm+!|Zkm!Jip<-6j)uIZsTuY+l8HgZP zPzg_koU9GDRFW5a6RDBpw}FCr5kHWv5Swcvp%I`nx=kF6jB}p2WY!~~&`Rn?({GfE zkkU2CAkJe~R{|7dj+~sK6{yg-y;=59o!B*&cR&i5np8i%SojjlYlX?zj{JiY)KKRRlHyHJ5>um7U zuw)O?sjF>~$!Y{gK(kn&e2{w^S$!UB$(ofY9m-PzM`isP?%c@~agkK}1`>E@TSwqRskHlX6xWdC zgY_1$F~33C4Hp*cFEKvq_Ths1O!@~_;mD69bZAARZ?)X3n3hcJ(FOolg z=QP~3`6os}Xv^Rsw-o;5e;0fMHQo=o~~A9Gig&gO`%Kna}>@By%%nU8W(2!?J3L#6%huxLjoVd z2XB`j7WqeDP@)Q<4uecoN}84)!!Tl-G!*FJZ&!|uoihgP8DjMzp2Wu1pqCAJ#j|u+`uq0n082e5QSuAEwYo7!Ldo-+cw2NzG-|R}9!3VMp04kIkO{SG_xld5fl> zzg2ON+N~~3Q$4C1B_zbiXFI7(57<@`>OHTtYmE?gob$zWY3@ajY+wzB%|KQE|{oJ#VQ3dkHSaN;r zN*J`r26>(qFW!n%b4qj{ZfwewCOu1Dl;jZoQohg{nblSC{jmwkxLcmo88j#;rs(nT zaMt}`3^w|IZxLl!Nolp8AVPc3B1u`L7#rmX(y6J*CT4L@f z`-3PDM6{_XBVxLz;Q7jKZ>O(?P&mi=5q#f$HGe6WW26V{cr{q}kW@M9BBtN6GAnJw zX3~6@^oEM}SgRi|>@_@JS^3ow# zI@DgSx7P?A2*txyQo|-_T-f5bM1}HaCEWvl$GY@TFXSe%XcU$d44ua%Dru7q~f{q^eTZW4AKS9TyHH0ty; zzz^c2wOc{Sy{VYSF$_!LSfUPj-faocBatwb2`4@-k9}dMT%cxZvjPwqW0jr{w5Sq_;>XIto|JKPcK9i-NicM&lw+m2V#5~e_G-+ zhXlZ;iz;M6XU?9Y6?%_T2@lt%-s+rHNdy+#w`L1mj9k{n>MErZwzu@Wc=6rmW?`eTqh{C%-&av8R{MYl&s`P&a>!1U3RSi10^&6VZw;a>iud z%>=?B-G9RpkF*sLT{+N+==S1ltse<$w)cc_=#S+_bf214#4Kz?OkGrWMv4+n*69PK z6m#Qx(w2q5ww?s*ed>u) z+q)=-{V0C06H_h0mVtN6X+HXF`tqiu-$_dIx>zKZpi<$2BklI@p)q92&@u8wG+nh@p{rwfX7`)bJ1rg!Qnk5!H*On%iy z4cG^e*>V!D^nqNJS)CN_KFL1a&?voe9$!2d?D*HvWXO80aU?ZCl};`?#K_q&E5dExQPlX(i@IjF(6gl0B<(5ydHJDQ`ZlGNK$3d#fj!f~w3t$$>E5>r~E5 z3YNExf^sT~7TVouUoZia4o*GENp}^GW%)_!6?cU}aD?$8e>tD}xX?({L&U&UD@~W@ zEa*2seO~-5rkO*$7vqF*iFmC3fYpRzhFt?Htc8}D$}cKFrLg9!`C*>o%J^t6_J!_} zWZy$NVX#_a{IvN703iX&^!Bq+aR34ikVx|Z zZR7&7X@eTs0RPRL6IvFA#HAOmrJJFIcCzGnd)&|G+(mgI%V%hh6lu?Y7 z?MrZ)=d{WIvtgv;@*qnu3Wju*WOkmy1TL!c4Z=F^MtUMezd8t-u0RR0 zE!-5cZ~hCmG%aBsOhksE;ay3weE`WK8GQkD#GeD~Ig_uNB{0G?$b&DqeH`hGfUzvz zJ`bkvSUPVhjX!$~thjAc-=VZl&T=vjXB4b>5lyf}F4{z{bi}_sGs}reDG_}kJxUI? zLJk)Fm4uq6N>Y|7He>CO{x0=5rHZpPgEHylCKl7OCGc2Cj1!_S7qCS=fOEf_*+QTS zAZMkB9wEM4f`Ym88KTot;^2@XIiC#BNf7|iDZ}Ie+!s=-SfjN4%7pz2S`%GsiuBlm z!YT$5A7x`i$@E;OQ@#b7m|4%cV_GqNPf44Uocz0B?q-Uw|N5 zejn0DZw@a!XmCV7y#(mehOuMlLANgwP5J}ii)B#A>+60W z)$drXrSG=4Ul6n9=5MbdCiz6#A|g-&%MqQeiYzphnp)$Z!8rG7FXS$LH1gzUw7JYa zf1|&u$+Ru&liua7Lq36N;TAjL!#Oi!ovx!!N~-t+krk*++SMA>Ax>R66j199qGXeQlqkLpjduDk_Koq%hY9V89zoHA z>Bs4K)iVCN2pub!_`J)53|nW&4Zzqv`E zR$C(yEV9n#MG>t$FO3DQ=kJLkV+V)F-tK zcXT>goIcBSmgS#4M-U9CPeQ^-hHw}8OG+=nB!qn9DnfVIgm0HrK{v}5EkB-T;AE6J z_X0UrU{7#z<*{6@@pV`{H(%dd^r>C+DgsoNtK{7yYWB~&8`8VSMr7et?tjEj?A>+l z@lV|N{lw5eil6_@+x%zz#PvxG(!qs%uexYfFCu#b+Me}kDg7Rb+$*mFHNIYD(`(F3 zVmhynJruv$0eX?!YmC^DmfA7>qP-{8-{RHT{)J`Gz!&g{g~=`wbTPq!ISoE~wG|Yn z^TJ6IMRD%Nl`GA@ab`|!RCy<|jEHS@+@p_iZ7s=G9+g|Jmsw(B?4^gC3f*!x`x>lR z&F4a|hQACsvO5RDG8=kGp5JIcNbj}Q^zgX3cb;DeV0&9IcB&>>*}Ho~pV z6t?_fy~<_87QL!v$QI2OiV4T7%s5T|fjagN5c4t;82FQU7o9OP0ar$HCTq(khW&V0AM+{ulg=VD9r@3pk_+;hm@W2}IV zvym>V`Mv&>bz@4AYm0&_+r#LfrHF^yxq=g!kxx)$(iFK<(N#LkLV`1+(AndnY+*C@ zX3nDt0(XZraCT$XL$Nqz_2kcB*232{d5^)deRn~g!KcDd=H|-l`SU3=xRp6O_;vXU zGrB*OyWmpLo-5J)b8*5lHC`3?v06yYAfUi)^|(Wd(4b^vqm0nGqqE0zUig!#WFoi8 zA+@*BPA@70t}i+nxJ9q>8M#HT>I1Yd%6)^Qk%0l6`uW0?gfK!T;zrHFJ~1e#$kFfm znsTcQ(WV4~TKdy6ZX3(uX)^Qgx8a7*YO;PdPfxc<<&vXC=wR_HN^K>umWOrIR_Of` zZk@-6Sp*SQkaxN~IH<5eG=1W>;8&HZJY^E9pn?AJtuTwNr~!meFTs>AjEe!=n(yWc zZQ74cL3zK5ESV>a^wLCi@G-{a$}Gf3z64gmxW?)|nTJLF={-JWX2w5+DUPb;s4Zz9 z7-Z`p8b-^-4OC)0bS9}~q(jyX7HPfSqYfaFDkAe8=(GxaY{E1d(CgsLNK+N=IUp9MC)6(#PH=b+o0+WK< z&m3Y)fq!<)sqT|@n2FvUdAN_J@75HQmdiVNSJ*mrLrrYv^941&t@o-D!aIJ)s@@&F z+oA3gb-0fHg*8s9)*ZMz-SEMtWAHMC(Ejle?DvsgcJmBx@2H*p>ev-DKkW^Os_lPO zuPDqHV>63e9+4@LrNl_;TpqJPX2YmJP2@aG>&z}^F_w%mI3Be?p1^UQdIp{3F_hfi zC$cyu>|89P#HwD-B2!Ttv%scfT*M(>u}sQNi?E6fvZKykLNwqz8GeGstG2TM&m33IE{~OwgiWZf9p@tmvfg^xusV#cGy%Sjxy>S2p#Dn=)HW-o@4# zB~0R)%|+G}%?l;89e>Q%NUE(ha5685(p?%duL|+Y@OXMbHFU$O$-o5QD;tGd0IZRP z<0#5r_}~VgF}KUeN^%$(IajT0>VYm|8K1YD`i}xO&*5#@t1Av^|>BUiF!_dPZsH8sDa%no4G5O>FROD+yv5$2 zh1=e&d)|;mHc)ks?rHLHg^Z{lu1CGVL|)gs1q?lRzVP_;?uGI=T#MuS1eLxF&2PNX zx8%s*Q1SZq@3HG-=hmO|?q5x-|M+FoB7aEqHfY42jWPpXy@g~00-qb|OXo3_i8fJ} zf6-8H!JkFUhzZjzVMkm*4LM(F1_F=raO3|WSiwGj9(nZl4?DV!8DjQzFyoVac@{Mc zl=lq)X){Kc18M>LwPd+*{Dh{hoqbsIF0vGNmS7s&Wm-MAVmS#wy z0(tbwj`B<&wqRZ2e28xu@TNn8S37Z2&Wca8l)4IAQVRi2oYjC~G^|c^CO?NHW{KT& zi|CT^zpJB-vZgGq+ewS2#$+@gd!4{{%q>x)GMN_5oSEC4EE(M$Wt~!jv{D-)8r0jD zK&W$5fYkJcc!3~TL*+obD^2hi#9ctVNNv%+jt)sEXG`xg%j&lfOR!$MhP!5+78skJ$r;Ni9gLZ}RlDH0vFE72wvFs@&RbYG_in~7_X$Z>rH=Dt!(5$jPgo(~dvYE+YyWT`7wSmkr?~U8)B%Mb2lRb*kX8vVl$S-%ANi5$Fykd3QocEt;}Pptv=7awQAUhL1HtlS$@WZ&H- zUG)#>Y08(52;UuGpJ!R*?|w)mbBeEMRQCg3im&nN)SH5UZ~D=&2*<_^A%=b;LMeuR zD8e6)=L4`n5j3U(2z)JywK{ENn;>N;y^dZl(7y75%tz)RWcj=ZfnE7vf(WEtW%vQV z2hc*Y4uYzS=ozZnWR~g%{dJOTx=Ra zwm8)Nm83hYX~0KPM%yqU09#QzLHA6LB$3lD9p<1VnK2ONbw=@X_y+DWtl1;2)RQaTjfeY!pr;nNCUt^-A;fnKW}c7Enlh7eR;bt}%`ogWMp-@<9J!MG$HSM_X`xMK0N*Kma?bTR2Oww61H#mK zWw%6w%q}P-VeXGegSv<3D>A74_!87cJ-fOEq9tz42I+*_TEl+zDJ zjIP`kMUfRsK~`K5CvWavrctbv%utcTrKB_|Q8tw*|0pBYw4S#{QJg_hcs4HB6wTnt zrJNikksD_b%fCodoIz5!mKs_iD8Z~P(!>k9s3YNh3eUQ)2BX-+H2Aa1pM8`e`356h z$L|;_d?YJ$67<1}-QtsXiv{rF4Y`W{?16`7XuhQ^8Wn{nI^BF?jN3p#p_61tRr2O% zAF#%Wu8CuP(rgh5dR^A~oGKTMDR}<>O=0S$F zA+Kb7$JikPqBr(OO&!D|!1o={Uld3QoiGoF(F&c|jJGfoebDOmT81O`&;&@S0abn` z*A&$GEZzf}&CeRmm5j}?c|_wjeey`Hv8yi9JvI~diq`ApQ}z4)9b;W8XelsiDFP|Q zYa)9!(uQC9Qlyg3=2Ut9_w#CO@mkkmFPfir7<3>MJH`ApgV231iqMX_{q6Z+CuqbiK`<;flNry zf7=kp+6WTcln!+uLbpOv+O=F-qMzCn62^XNn0t01*cR}W#KK86ZPnNEv{LE{ga=qs zoNP9^K>t~gu#+|HBiD*MzpA5h<#zGt5)N>YoOza*U6zMPJ7Hd8zqYi}a)R&yAMjT9 zKWN~7*tH(+hL9)%*wd@gJQ;=TiA!-cKi>+haYNfmG~vY3BB-(>bjXimftJ)=*KKPS!7LDlOAQI`Tb@&9GIOWEmtFMan>}O%@%R8Q>vEH25~L(b%OF` zoBg|x%7N-yyzk(b$9#2X`m!5D>O53f#!j^(hmAW zZvzs-v@v?7DSE?IOoRc(XBvH*=6^aQ675f0sQma0cKu|y|3uHKXm0ugib$C|{RX|<5Z@KE4y9c0W$CsY1g%rPI%w$_(z4h5j7|FbDMKXyQ`DXAw>z3jqjS(p}is?67L z`U}0ja7t8ei@70nlJe=7Kf3qCv^{r+o{2Xpt|{rQv*19}vFhMu8X*x;{G>MeEC`_su)6VlH{$3!Sra%{s z4tz{kxkJD~#HD%z=m>FChlh{P5($w4C;ulZ6+s25Q$V4QLI<*;WCt3BxQfy(659Sw zhOHa*2uSeZp_XvKyQhGiaI)vtDWJ3^vi2BfU{a!P=(ND-;hIaj{iCKhrL7i0Evbyk zt+Aq>6rk)c;$j!4Jn`C!X8GEjJBf99!(OBf|J@4kSuKRZm5ljs7pC?cpv6(F`yX}} z`RVbE4r);V8C$|X5RDaQw zYhrVIMf2hDU6vj)al|A)cWKCwi7_?S#AK6Y*s$1OVY>6+*!N?}7g3^9G3o@^*ZYn+ zm7dSH`w}jf4h^~&rvBI*RTQY&Z+KQ$57ca>)ES5ay9cCRIxcSqusW##w|z!>TWUf! zwJyf*zRL6A7r@?cNVa>R$wr9J042UcKM*W4&Hy9L(dJ#M%XTn_-`6g?+%df81p_({ zZSn=i>0`h_zBncr4pW@m4HqNCu-;{UB@&;&vY*DXU3>Z0cMGupi?es^5(HS!MW;1w z8`HLJ+qP}nJ#E{zZQHhO+rFJ-=iKa_vsSXs52*U|R=s+#6BgXn`nNvu?F!?KPvtvA z9G@K@@>3On>K*wnHt39+qdkB=Q$YEHX2M+>s5r5r1yNZuvH1$$qrm_WGKPbPR@7N} zXc%kBcoyj(FIYdFChm{i&@*#<)hwH2vjtHO_zvsObU{`^>bYMUKdMoO@L*;nd z_V@;K9a}!Bn@s-5-@N|&Bh~YK*aN_Rn+Y|e@k_bQ1&V$lKNzI!^W+#-fv3UV2jAvC zG|ox~u|{cCi>syFPX&I?vp!j>15W0tA<1=P$}~h^*Kh0HYmNWOCJX*ZZfyo;Qc{b6Bi*GI4q!*Doa}B(vM#Ml#Tm&sFo|f}F$7o6ZxTuCV z5iqrDD}$V6d5M#|Ar|6a7C00QF*|ONRtEOT_$bRLp-&@M>;(EzSB$AD)I>pp(A1XV zhC!oOBXtNzcr+mmz{l5C?m%zZPji59h}zbVPiFZ&zu@Y%)&5SPy+(p#io1v)GN5!D znQ*etQs`FktB68|2G3mDHd^f%fC$1mEV`h!&_e&eJ&_N3_qP%U(89>q>dyg8US z-mdC2L6TV*XEclHDHEpY9J#;PHt=g$rDK6>KdK7KNzDy0YEfPxgxYMoth9}@%D1%6 zflVo6Br4!E&r(M!yRD2s&!kMkZVEJ&BEDRs_fC_M_U;TZ$&i`$s44R)Wgq=Gk4(s{ zdbGXNIDB+t7|e@;qt^$55JPp-(8Cm!53%ys^nr|M_lzUoIq^f><7~VJdgTel9x2Rc z3!e-)5E`X@z!D&f$jPiGoH6-hzd9g)} zc=L%O43x6F5XDEWd~>jUz%rCP^YVhTYB8tnqO`v{n&(f~$dW*PnxFwMC;;BFA=wT2 zMPL82CosO_E~5hZ^{ea$*7$$3X8BiDm;XjV$W%H1p&-D0TgBH|uJHT%A*oZ&fC8*5 zM+Qi+mUl~xm}_4OJ1r$c*{DwRKemQ8=bddu<@U~>)cgHGRKeG^9yr*1+M z8X^k3+CFc!GIXcDZniq~Z-0Niar}kffX#(PL?EU^?z;~OWyRsAp%zUUf|}Oe(NpHf za^P$y)%$UBbxt)>QMK_6E~oU68<4HGe2QzEXYf3 zbyWTtStl3^Nv*fhxfn==2ONU{PaDOh{VhtdHb=ET6`D*_K!uKL7@!AVOi=;%U&^92 zr8!pv5E=Je4M%nLQ3{we)##ad5-1pnkdOTv`*qX*>vCbTz*(#3Z!{aM zHN?2Nvs!A7-pLC%vpW3(k`Y#wdBVJuMk}k?TEBqd{EjfEnypGcUbe8V785X5>FS~` z(@mTrTBorQKx9J{axwe~ERAgI?5jD-?X0k8Mag+tT)mS(YCR)W)vDq08HE*1C6WEf z;{2%n<19H}mJ}g9+k6&Qcn0x;mYs%FMV87k7Hyj$U_nb3y%L8B{8NceNMk;WA(Mxs zhP*>irqdh=punx&`;nU4KezO{FN`LO4$GrT^2>V)=|(gsLtF4bXz^4*ULAyF#V% zevqXI^YYWakwb?ya75s7zQ2(P5g?e{=)epKETt;NJ#>$`?KwB?jnwJYu6Z1%0_ktL zD%gYPAaD3%)2(iTv%0t+f2nZL@m~ykFG>fhqGG4AjI8fcEM=N@E1^xA$;oO6&?~kqKaYT3XRRf`ii4*PRUzg8M zD0Ac|NN6pxslM`y>hWo%m0!*Gd!VR!_46mWIuTww-M?o5_TeIf&76<{E^=&^dw{@z zcnpShv3+^qCJaa_&rFHF1lKui1BOt5%`6M;U??RxvSS{c#ejI-6fa<2;ompw?%6EFf4DVV@I0e@_RAlJH+ya``u7A*N+cm|>C> z?qk007$l$dYoGln1wdVDLbT%QmfyvwV;452U3Y)KG;lMPIG;8|#&M#KW zXU(sVgiS_;lj~;(FyHT1rsw#MSWX1zB(nGtHDr+2`L#Vri}=D02_p>@4H*=P(qE_C z<(3S>_Be%Rv!3W}iKb^Rpv3sWKK!xaO*qzWD&im6inkyLv#Ida@Z;K9#9-Jk`+-^I zeN6`m+@a)Pt;Y!3%y6SczWGCBVGm~ea{xdaV!Lp!@l%=Qt+1{PadeRI=38U zF13_AdP;s-l-+cGQ-$)6E;-ozWCUF4Ug#m z=F_1mVpW}&Lr>%MbR(W%dh8mKF0%a1uVJzc3vI3JIi;a5gh%M40S^FDixTBp280TlVR_oML>c36i{lbI6V;Lmz=m{t z811uEDTD+-xZW*%3485uRtN+>9VJZI8Rt9HoE<(GF(ppHlZy2OsjlwH1-U>N`+ArO_E6oTI4F3c<~)LxaK^aYl9 zdxm#u1|AtVbuaAio$JOMiY~{!1nIqsNL^CgM7<50Lj3%&(UPF*9E{!)&hmq0<|24A zW!Qq36ks0m!Dyxq>@Sdij`E#fO$0JOQ6Byy8}h#)Nh_NED8(86U&xM`idqhHKfw-( zl!hi=+NfN)Xm0j8Bb=K9vxaIhJeA}8`@#c)LJ+UlGv`r74aauqN9&(w?AAI2Dgm~X zwtl0N?RcZ!h356~eOTsKyDPrH5EXcHEuKK%A8?mivb=x*D$8(EvOGoLQ!sj{-Qu=f z4iBhT!&37mMG2ecbj`{%6csD$Q+0*!J_~Y|jikyX*UG6%)F6XQW$E>f6n0}UE*6Un zJmop)uQjVo+w#0jMzVTE`f~MqRRZX>_tBX787p#T`EfihjZfW_Y^cQ|!$Li~${`CN zqHsTH+MtWUO8S9yl;P^eUx8(6*MgMLLzbd+l>m z2x`92oh-li6}g-}K44g6!&t;0bokw#7+)^|C(0?Hz!gtb_S7rQ5*$07!n-MTl<={> zLxIS(<5tBg_bIPs2~RJ(3z~MMvm=!I6W@B;rMD@5bPx$W-DvRii^cn-V81{QWW@6t zFqce-o|k;5H^DkJQyt^13M|W|j?Pu^S2|e(-!(h>9s?+`aKaMlE4V<(|mw%=l zQV(EdU9u9`AEAi6L~Mxg5D#)a%3XRhTFU*f>O>-_{O#8V7T`88@5}PQ&JVxhf(P0z z1cJkIgO^A|8dX2`5*pbN7w&mWAR^)6aUZ0?Ts9MoYDW=E%a=T4i7(o z9nzo1m;HZz3*Qf~&A`#f@ZV(W{tvzFAI6;X)mGzxAaWG=eicnh`@(*=d7i^hTC2-=SKqHc_GOsnElu?dK4WK(5Ku)hti{mU~$j44Q=3Z>E3_ zJ1U2j;s)8PkPyR3nLVRs!TiP#5$YCDyZ&=aSG>TXm*Ys--`^Ax+;+VaTDpt&%stJ;LuwYQtQJ-bPWR@8WnmLD0up5zS56hzfl%F|hDV{IiX6&J+uyb)5nAojq}FF9{5BWDz;tq`h>TCQld zUMWIBZ9F;!?;cL+*3&<&TdXsV6Z@+BeL-?y?{OXDk<_@0b^7no2J5N_zuBIq7jkg+78Q~2_) zja?cH;K)y5LHFYY^FIwce**d+5&2(Z=^x-hm3JQ`73A+JZhDUP_+Pt;i8q!AqPUa+ zH@3ORq9MTi{9@vem23aTSzEa%VyJh^v1*jBD6DKKVZ2qUM5rubq>|8R7%Xe7d{kBR{ectyVTmTf^j={&-tw4w&hq%N`P=Zi@22U5%E9)5&4Xe`6zC&P;lnpO zdP~LBwT@}U10TMzBhJ>fr-^@e-SsBUPM}52*1!7|F9T|a1sleSx69xf(#tb056i$t zwg>;kO}|nj(_7D7Y$V=6)R<=~d$Djaxv@*P&?ZVQ~ zmcK+)wTd=^%WrQ8=7dReiy@7=f@v@HO1yINOp=L&6vSfmbir?m1an)nOKyUZsg&JP z66Qx#fXY?mg1K)wzjOr1s~}Pq^N1Fg9BqorTu3v))5xsE1``JOgqB?|B;O{mBVlBD zz&C}t(%O9!H^ z6y7qd!k7$1D3ioVCV@&5%pze`(_=G6m&}Fpix3^fam*VpabzPt+t#WJ=YqHp=OTV2 z0theQ@fc6a_Ez*GF&6{Qq9hm%bjYh>zcWL5o6VV5_0*fn+}n5q5zIR@7SrSHoMd?? zks!WZe4_Oq1f3B}*IPmrO;*d=aLlXYZxs}~KbIEuow~O0 z8UT7#p?`T3#S*(z{0y4cw3cr9Wk=aUd0UBwE?N+EtC>f1+;~;q-V`^%t4(1;A)Rgk zD$L}m>x6$RA(ye>Pldi@C6cs?Y28Q>2pDQzNwmecjNCHd+H3q-c&@;agrGDSSQ}{2^wJyT+%n`r$@kS5bwF6qsGMA#g0NsY8%dl z5u;m4YU>wDNP35qgy4+2qE~~Fc4vj+Q;)yUX(!$yek8EGp*vKAtI~Cf7;c2NlQuDo zFrdG$%w^ZdR{w}QlRfpM(|h*{cLeIxu{GRKbP(?^zeGlC?^%UqL~Pd{UEe}TeDV!( zP(H#`)pYtK+>(5#4e8vd{LTw>No^k}x7o3|NTaw&r06(D25@4a@p3FQsZy-XGN%<` zi(_sSELc@^3OvjFd*)Z|ucTc%B(bV4tVXp8wWtno4nYo&Ts5S8F2BNRVN%v=T|^W~ zT`^C1W?g_4G~^UB)AA+9nd=cS^cXbLGKCv`4QXL)Z&_xdm1dpdv4{t7KeDdOi6~yj zv8UWo*2fN#x)`@^Kz^?TE5f~=+JWQ&VC5D*$$E?4P{{#N?!ki4+BvT@gw6z9s`O`s z*r$Z7xyR#F6mSXEJ|;u*2=Z|G0@w9@?qK6HkgZvE`|h`pb2aXHyS#g~zWS%dG<2Ki znQ(b4h!Gz%-7qpn9QL|rC3W^9?~jaq-bTIP1lZ5#-@ zfsxSrU*jQn(k|ozSv?BH8q2^)ja^5p>CDN4;_EGa}?C2wLp(I4YPR!8m4rscI5fiB1z-@W0a~T7j*~ah{61m90)d-&Ub1w z!Nt?-vTi@aUv&+Wvl)2P0=I{DWJK$OKk!6`cXD{iyTGOljJ5|tnNqTyl85tdWyx}VVGxQr&pzKyl@P(e67GBo}=I;R@Ru*6n2NUlw z(l2c9yvd_cYZ=Ld$oR+myg4M%DUWZ%psd@tB)zLyZOWDC@k5Pe zk)Z>CX!HyJ>QNe5C;k$TEm6cw>eE-nUxg|Y+4ganrFEvGTx~H#lQS+Qtk!e-QA~;p z$8RO=U9+Xd0t3}TYGQC1U$<|@5}>kaalT|YXtp1J&3NKveaH0rc4Gg9i3}Yi<~^uZ zr3$~kmeV+BN`*7uN%N_A&L_50Op2m_J9Y!FxNp6XAKy1Ggq)WSxZs~Zqq_$dg%^q_ zx@-2Z%X!u7AiA%_?*<9<0{Z(_25OgUgMzZhs}F?}*K*J<7akUZiWP4oEI2@bm24wW zq(aaYiYTCS;fx6%4@Kir8Xqei62Y8mwH_LvFC{v9&j1X;-k(4uH11M$U{eY@7F#=D z%dBxoKNpB@?lCWoGBiF2_K}}TG3`E|PnEwoTwXsbhsSv{2}BcbjrJS^1p?pwAQQjA zLX|f`n6o8}YDtkSQV8png}hp?bh0~mteh18h@3e-;+Xs>ob`={-7f&xJrgpI1Jw|k zXq0_hp`-%6{|)L)xF)6r8bw7?lgloC-FLG`X7NdJGIz`x zRtzG!^V{rrux6fG(YegJ4m6{pyfReWL%)`Zv>p^Qb1{}vIWu?ZfsmZc;GC8pC3DnG z`NA<9nWM4?Jjn~6^SjrXenud5z-R~CGS`O8E?v#p`PVQR=Cr`uzW^O`h_`g;f11+u zAA~p8|GLutcVlurgMV|LlQMGD`_E!KGydQG=YqDS;#=(gV2I;-CQc(EfS&pN^(!G) zLQW(Pv^8A>+N-l`3JtH1T1uDwLIjO@fy06`@kY|WP$eQ{LqHnCq6iZupFTZ;hQ47Cw;6ei}O1k~i4=F0)K^!MFJ26E6T2QBQ8fO|(;$D^x0 zT{WBDkcIQ~RO;VlBp(0bb^d7p?$_Up&zrqw4qQ8y%BGZf>^b}bP|k{Oyb*95J zTAq=e(=xvcnWR zmgYxSqNC}ct$O5kv7jHRmf2X$B%VLjgHNYbe>nVsB1)_V0|fsuTWlGYU#4kv1zi32 zmAY!6fgV6oASbmtYq$f7c*}t8_cueWEuMaYZI+(bP`^HD1f-A_eJN6Ze=2?qdw&p0 zeyW1U>U_FO8oY(0j6LpRFGQdySDQNe+a0UW(%?&8;R%Rj`xE%Ym*2tKlh&gwV}@3KY^GI`9BMk|No`>zXanys&%Dv=Xv2D`V&X26_S1L zWFT__A2<59NeIPgQcCO3}&nMqI!KJT*>)$MH z1sM|}knMzlNUy0YbLXRV8)FmW@2}@Y%wH^Wp?YB9a+G>%71qLbkT^rO*v*5sB*NJ^ zk#R?55i7Fs4vlUCqB6lu9^z&Isx;HmL- zBo>H4G(AqE>69{t{4!%K>(G4B+U*-8W0`_BW3>yAAKy~F)0Cuumf&Su#?5{LGP8)r zZP3+s=}qVvol_$2@&JrU3nhOx=a0jWG=+0?s>2zZstpSR>PmH0AjQw&h3_`xRx{z+i~3o@5B)S^>iA^dbYqd3LqybR!Sb zU$1%>Gm3EJ?TW1?d=U2t)|ue4eG{iHqDET+p4YMpW_&zl zmsfS=rkXVCS(8Po^PK@t=!J%P?EtT18WT^7LeHt(jWMNMj)w0Wb|YPb@Ufd)?mOSs zD!Jsvx}2;_z04RShYs~hotLhcgBbnGFT$Lh+gbAanUVIKs;OH=tyyE?cU?0|8JnQVb(~1oiZrdh)up z_(5s|F`~$}G<;X*#AmhlhX0oU`1L-$8Mr~Fv7PnCK2uDmGZ>r8Co+D|IE?i^VMY&b zEn-SC7Y7alzlo$lPz@;A-+EEFs|=qyl2-n>a_V+M{k-XSC}uE`n(!{+2Rab8CC()W zy|Tf;63EErnXChdN$dxvIIUq&Z^NXI8=XC%j%1T?hMnI! za~;U-4MVAMi1H^hq&x@g?1o(n!v81=D6y4}Lh;%Q3I^ua{(VA$JGMw}rtjWrBTn?dLt zC(GT6vI6SpDRM+b7o=cVKgPm;tH7E$G@UO{dGx#SROaLZMrz3AB9up9$x>vOGHgty zo`k|BMIgw#K-b;)f}rmDE3V2wxGBnk{D>23BF>8CE+}B+_z~5#k&o*he#pa-EN&j@ zRC(Y+u|Onts{-FE?BP5Nij>}z)V_e{J<+sCNF~3hamH$yUE`$IVio1>B5kYhuNH$k ztA01A$Fqk#;sW^zmiq}51mkx-`{A?c+8|(`M_#@@(A&N z;nWsc30d@TQ^6S!!CLmVmdYB}Ff_{=8~pwm+v{r@W_J`lG+z9_oJ`jW}>$^m+XDzU;TT(ZJz+(Sk9* z^#Jjay%7QNxzl6XTAs~D{%D7#xb=CC!H-dl)rE-|vS)m&h{8KxH{G>`)9kK$A;z$8!i)D*4SDXMPnAi{(=7wkPbPbUB4aj8qd#UT5G+k}w`;WL)Y8ey z#{yMMK<7^V+2drb22I@Vfp~GL^m2mSL$j$gza|X0iQDkOtQAgBKziACQQqliTWeH= zOCV7$nziDMchqeJj~iA{SIO4M_Z}whO8Wlp{kn1oqwb2qEvjT&N9^UEYsLVsQ;UJO zfrS)*hqsM!2_R_i_jUEiVa9+O_ItdQC9D{3QoYU5{VJ`=Yw{c&SrjDny$H;;CG8Tm z)vz;a>&S))HyK%JcucTTEAU0Z))abQXlS%-%xmneoYWkx4qE_CUj{W3o7x1yunO;jVLi;j<%ys{EKi?+T z5;k5*WP&jlzgD0$+94qdtmq*37WufdF~aQ)-Zh802j9Y~HuI8BdZlcED5M~wTV>2f z%HVFlEpL&us%xP)8=aIS`f1TQAtOqj37m6&DMo&c1gM6G#iQ@@+lDOSNH{LsjfKl? zHo_&02=zwz-o7t4+D+OFWxN|fW3rUd7^vH1imf5jfYtjXQRRO%j6=3yEA@i zN{>CcCd3Qb70DVY-J~2PgCqfM*?9GeFHlQt(oG^F8iFnDV^TJQ;JW%-LePxdHDb0* zKP@>ofDWq&B1xt7o5!Qk z6CXd5Uih#}DNJHTCpys+jCBtyv1D62=KlN0b%L3VV?xFw}M&=M2Y~ z!BgwBoNKmH=P0R)0u}`kW&QvbHH=9Yq9~EmDeTP|k5DT(OK^;rka-wZceQTBP)N4Q zSLy399h$caqduqFS85IiY*hbBweQ@}9f|Z)E7pOQY84Y|QR_WEg!EfAktLIS#lNCG zM0t%PYnK0wm9Q?^s?{|iE3vx}w4t}Bb5o>#NI{I?s-9?He4ab*zjk~?>|`Q+w6cb^ zI#yNLWV6g%I}A&amR?z;dp~EYpaHq6Ije2c$PO(01l@PnBpYQRJ1{)qjbZ>)VFyN`X*0bDDVXNaoRjatlbNH8e+cUaiFbm75}c}p~G?j zfH-`>r|^U4spVqNk6KHx8S5{?ijh|6BHBJm+=UW|JL;Vr+i;P5rPekvIo51F!vYq- zo?Us%B8wi&EaD7WmSQW}v121lnVBZH#M)Pm6Z=5EEv?PFDwi{xy|VHM!@y6n3XttE z)v!%gDuAhVttFEo-6cWBQjUosDC_>cxF&~avugzydh$S~kX2+cO6N9|a6Mk{D9pJv zZmIQX`uU>j}yZ-E%Fc9L2s@F9jD^so_(N;D(K?$Bp z?6=aEaiz7PC5j5M3W=B2QZX=VGhKVZl;pAV!f_PWzGJn5p^cPn^lzH_)l|))p{GH+ zDhS`iw;V{4WA3K!{rAk+j_e0|Q>e8ZpX7Cm?S{!xYNacbW${g*nH~Fy6CfE%% zr_HO5TtJZ9Ad;d}VYU~j#t_9G&+-Z`=jk1Gi z7ZPYL)LaQnvKP_DTgI1>Cg&!QbOREzjMFo>-YxLr9F>mM+tD(GrNlmuN_w|o{ly>2 zR}zGK{#xy+g!1OuLa0jH8Z|i9!B5`xX2R{c3b>251(Sv*_^fpP2qeEkadhG5XWu>F ziOtQ-_2)1=vCbrm2{RyXuJcc-r;Pdb@@Kkuk3aK!N%omX<1kH4>Uta?C6(7-WW_n#l}CJ9+ahgiDRqwB+yxVvY!$*<$%_iNGhSXy3BgL{6@g@Ob1>OV zryz!Hz>9H+aZl=c+OMPX5nxnQ3o@@0ZWw-Ku1nLDZlhBpD3uMa60c@p27>DQ(&33` z0b^!~oW5()O`8n~XA+-(dT^@*xC`r*pTM^mBVrGJ$Hxm+hc{Y9E+P(Q1rXRBWxF@u zN%B;}$ktF&B}p#|zmdAT5zbkHjP`jx6DT7L|L8JxGL1aU$~JQ#Z7U~#q=wtJzn6NN zCak78HAFR!mW<~_3!f8bj#;NOK_9s25&OuIUv#T3Kk`w(mQ*!jMW)?x*--%v7TZ=5 z&S!L}v5VOfnmK4a&s-5Oa*xT6q>w8WI`>t$4n%nnVA~OmQZ^Zo6sK0TYTKYV`>Tc4 z%Z6*gT?jMp9<~7P+>2`(@l+2nJvrc1HD)jGy1%;tSsysiigb7&cxTmv#tLEdSboEY ze4}xu6JrSt!5d-=C;7bT8NNfZF@6N91@96`;vUm_dRHBCOEbcD@v_2e^YhTl`RS1k zl1dJ{X84PN*)jsv(<16Dbc@~7Vh3v65cObdg=&n3L?xU;c@$h2uMrrrhF{zCUsAW% zzbt%ef5+1z(84<3$5>TQH&4@La$T|c(d@&3>Xf+!^)_l0h?jkWAN=Xd0cuHG=m@4| z^~L)W!XBRsey}Vlqr2ia(Kk^{t2yHf&5nWRiVXr;2T>2BX9$?jZrjB{sTre{;)RqC zt2Y6Fl-v=aH+F~@A*HLSG%6QSO-(hy9RLoFL}aTBS|<+UoaL&j7zCveB*X|KD;$a< z4-`)OJDd(gLN=WvVfOuOE`B{nIQ3dgrxyI8^v-yjE)G_3<;V)e z*BBlgy%CWO%9r2RdkRwbbYkUh=>_C!ndwn_dqo7S>)MjKa|$VxCDcw#>dI&2j$vo+ z=AcD)avQ$*+(lfl-Q+yJamlnT1K6abn=@{Efe4H0MU_lEo&o10LqZGN?hyqa_qDNc zHvG^{wuk!WR-lv(D;V-TmA$r}h_DWf+1wt#GMlv1+8*_HHC~tp-=of@rp8>@+J<3r zBlc4aci_nnKcZjnJecS5JwH{G%k`=%ad4OI03jHws++GQ@0K>KZMZ^)wGdqFnuYt2 ze4I|>9Z|oCZKv|=95d~r6V~3K5?EoYc;+re_N{Pi2%e~+^y5ZEI1V?%!6lL7UoYkW z$y|o_kg)bdi82F7SnuE*kg^8!<`h#MaEIwKuzMW?fTLO{vxb+)zIF^!YC{2-?!k=z z3|@4_T}i|_(njr(rRxLAa2Rq99NiRqrgC-AU*679|5 zj(h(-{6kA0no%1w;{Pd9yXRJ+*^`*~b!rf`=kPR<-95%_VyJh7r?^r-mfwQ=<4P8R zGw(Yq9zn4<0nwIEdroTpvZQksquTi+IMGc^;tP3ff@*lY(TdYQba8Appq}1M?CW%2 zAD!#0z}FO+*&`H~8mJ~xR=4&?7>sLERJnKKWcrPwL6Ti zip~qw;M`mI0dI}k*8^Smc~^<}y&1jcn$~c;_}M2!8eKA5d7P0x$a;@W`pOI2jWx)G zF@q?3>5bdvf@sl1O;*)g=mzWA)%7j?1waIy^I9DB*^1Kk{)uDajV7kqGAquvo1j>G zJst($W=0;!$0q}ONJM)Jp-)CmGNoHkS{IBSx`Q<14)g^{0lI_njrHTV_7q`u^-gfr zePin_ow+5bq)(`oKQyRQO_MRZ)M|dar^mKI04Uiyo^mNkTfQ!u+b6uy0u=37qOu52 zk)eLHqBRM_-0JZqCai98H=$4bC%c)q~_gZZcL6dpqI%W5>br zS6n>Y1IOx0)gjr+SprV{MImU7%IdUe&Q(q3usw(D&P^ST+pz6w(Z>$FrPq`N%ECpRJqy-yuM7f$+M&uwBNtBr0pdjuT5R>ic3 z`JI4(zWR1s!!`5a3*Dy|6KaNq2#6dfhJrt0RwJcia@cUa06mun;krX7T2}j@$?yX?8m9qrtC1w)JNca_l?YMA zceVVKq`dh658LbH{HziH+uRDO#{Szk!%teU+kL4wryd3<54DmQ_cXh^}$PXl#7yte9GXr@y;R^3r%{ znUiClt$oq?Wl;%6hvUz4^^*FDZGNY#vl+OA9xSGR!rzENT=d{tM^>)35xg^OE-;h* zZB;*D12uY|sk(y96`J33k~FdHjED}#RZDwbj|(ac9U!BG=En3)3?TJ}S{>Lo@=f4MqO3d5(trU(Kfeam&BcWDWnzTIxS$Q-vxT zE|`nRUr|&Rl&=FYLv-+mdxSwFb@61*{5`zl8M^wmetgor0TRM@v0SyB1jfRl&<#i@ zf$x=MWSw$rfQ6cfH5WVfZYN^`%leg7T@Sf3TIDo{un&dh&e3HVy3={jPpIpx#hZ+v<9yK_kRdm@ehI+HtqP(Umb6+E$Ki=% z2l45ZsJYJ84*N&5ac<+&tqSfdv?L2d&iSS)L@+7zs|4N-zp!KkB7+kTv(s&FCb@=| zqXHxKcn_#)I8#Gl)kxX`hgtpw57r+1;0=*!NozVOViYDDqQ^*(bqvB+IlC!Ppuu=HV~!wIl_Y_e z@`&zp-=2#S(9TI8n9oKGX+3SOg;JhW^FifJI`N9=_BiONP8X@SYQCe@CI{d7t3%|p~KGKw= zVjQ&E4&SfEyw_T?!u3RC!m7N8kyO~Y@t`Bl!>F{X;VOC(VE6N4Z|d|6`X-%48A87b z9Tk+fbYli`9M>+o@)KtRuW^vH_%mO>I{JWax5VG_&c{&8m`aH8V`_M?$B<@st-LDG z+yV!v`ZdI-=&7e(!dpJ*ijyT#GYogicP1G#AWef5h&2;|W8@Pphp%Ib1Kep1kkZ1? z=^tn86!s1j9#XiqZ!WmCK-+OI@KF{owFBdE9pboXl@belYG z9~EYwzR}^9K0=wgitK51klb=}$FPPrpA1$Jn=oa>y};p^r6iN;=Q6K$@lP?t7cq50 zTty58QHf^^4I@ar_zyU1Qr&`cC%zC@<O0NTIBR-SVtd3bTnk zHJV1wvin=HAIkP{40WXbox(#A`J!4by8TRvKaR7)yi|>!qx@$bgG@PGuH&QD%+!m< zfRZpR)hLYH?M<&Vp|o{XU%RKT?+PLUeHQ)Y5z<+e%3nqkK-L(zGY|A-gF&Z8Qn1DIseieppj1 z-*_+2T#UX^K2rGSVWV8CPA$#QElgVRH2pX;e>pih?Urnqdq^r(aP9yn7Y8vXRM^AZ zr2$d%?ndiO%Kn#RVAx3Ka2etvuH0e1zpxKNJ-~gHZFdnM@ zy2|9FNS3*EEbE;FHOdz4fw@ zTTv^J`K1H8%uT@2t_X$IrHJOKfXNAtx4u2(p?ev<2_`*;&V1A^yMRW*5;^bTAcY&Z zz1xG+FM42D0He&XuOLBY@@ec5FlO>=P$~|rQJKuB`_ZiM>u%GpY^fBC%rY-23WC~% zsj9p=5{qw#AJt|#*D{zEM|W!t3|8Yh#$9`jdU|7Qo9dnlY1RcuC_uJY(t1K9)8tvm zQs7yOGI{w$mJX@1ra}xh8~`#S&t`_mnO3C?Cx)VdnBH^l+2k3}X5;{eQQ^gg1)|Qp zqo3DhNlV}H&~)`=&kEG)b{mnwveH{2Rl6=vwr#czffEaY{&NTn3e6MYzWA)^4VJx ztFlo`Ae9jwrw5)Zt#H^xFi)35WMD>gE=lMvIBq7N|H)( zVuNiPqKgN=z3FKuM^xsP7+z>^Xw2n+T^VBW^Onc;X6^mf)|sPGmG1Y<{KSRlb_dJ- zQ76mu$v!M6ux|RwF+Yd)^#JCLFzQwS%a70kq?KzqqD}vL>mv**^eamv-c#FK>`whUAcg!G?OSQelTHyQbuV!q+TRalw-Tn>t5wSf2>ND<& zoqWzay00fYlx*EwF_dikJ$TQwZtozCX!ct*lnm$@>Xoh8)PMzWtp@ax(aZUdj40oYpt6rQ6+@4lt4g~06H7VwExBVcHUXkGy$4C1_CXe!-}T-dfpT}Q^fD`<<}kRz5z*_z~*w6Zr~ z2n~M!wjR!E_=Wbod?5E06-=<15kQ-fYLGX^y__yCRnsUmc;B^#M*X%-s32+3%_G4* zajA&BYQV?kDm*=cAzRs;`Z*7N%;gOLD%OjqR6PRL4aGzW$RLEq>9^#Hxr~sj;y*?V z^RBPuAn+@%NJ%Y3uY!H?2F4>^^4SqB9583`Txsy$;wYpf284j;_EiGM7R1*TJxyZ| zi}$S22+E<(X5A?0@Fhtx6K!W;lXmw5Z$U%Arsc-wjx~u&!|7tRcIpnMaa0QvrYT6} zlFtWf;?dhUVZSG%mWs&R4q|Eb1xq(y7#Gkr+?*2D+O-8}uxGYc=KJoe7ejfGZkpwjM}a zMFiyO@oe(plSiEt=ef^JvoP|Oxjy#lab1MNPC-YW>P5m%SVUkP>=YX4d2N6R5p*K< z!axX>p{ygcpQFuzE5#~dPLl$;s$3vm)UwoZQcP@#FJ^!dUnJ^R%g9l`=Yf-`WKI(8 zc{CQzhM7j$QN@^mZO)~zu>Ap!Up7q7IJoBIxE?(iQ0wG&{w1lFHO*EzEo}TJyih9( zHL?gLzUg8F>0QbE&G^%f&Z!fDhcf^63P~kH#(-;di#0lkQw(O5pi>Nce-D`rFo=Lo ziv4jGjtNqv0_`A=w<^`05*HZ_snNpT#zS|6C6CE+cm1#~bM5W~FiLE&{R4obvQ59J z2{YsKh$NtYGJ{#sQD3rGN9hCFN96_<`Fo%nSh<**2MHqD+<0Kq`cviB=0l{{M~O4& zyVMm+hP0uQKLiljtFJdtR;Zg)egI2}G*2~ds4Zdsn8U1pg7O__eEs@_Brme(KMb z&R4ZppD0{OzZPG)Tt8BEyyIL^j(Uk)zmuGN;5YVaNtje#oQ6_aNl{V>eB(xERs!Dq zpgjtOYK38K*dPYVAtkx0rM}!`UeKWNuCibzc~gkHk|mKZhnZ8Y6cR-qA9AFA`~Sz; zR|UnPrrQPr!6mqc;O_43?kW>OvDu<0RR}+b#(h|kR&onO{&GsV{cB8*G zee`UHk~{EKc6=CSkExR0?+gMWcwnu@3GZ%WYo zT5h*jgu#w`?Ic8%r!19ovmap-9F@WucNV!vCi?@pl0&AhXAwr(SXU6bX4`?mM2V8l zmVfaU2}?dPdcL(K?cr{0xQE7F?`t)9Yi724?JHR&hA#i|8aMqT)r&J<(o|kHHSIj` zryzN15@{T7FIho(7oB$WMNl8kP`bN+<~06kD>EDVvZ}j9FFo9esH(@}Iyk9o1AYVD zVC5s!{tL06P_DkAxPA6#o?)a5YYRrcX;^qC-~ng%WW+8EGF_LU+c`t?fyd^`Iic_q zlFLnlOOvfd1@TuXzlkq$a-Uq^N~A`iQ<1nT`Q%3zYd0`Qe&zdj8*f)5fp32ZE?qX> zM1ZtVz~0v3$#@it);Ll9{gl7hqof0%SmFML~wDA^@(OcA>HM(LoJe z+&*C`JZBS&QqSOWBQAC$aZq1w>9$`#*8g2?HK}(aX2r(0*#ya4yGW5qnr8^7q5*n- z2_juVpzj+(RrAkphQE|uU<*qhenEIU;K^5ua{Ag*b;^Yo4;4gpMaY;K9hVg|RM)%0 zUKcBhokHF;fA_pMiv4)6u{O})w7B-M@PY^yKN)(bWLBfw{Tjgp@!frE?z)CY9ytxqXJ*x)z+V&f{8j38Ck@T460 zsS6{(Fh$L%*Y!ZPnW>|sxnJM`Uqr9C(Cc5tdEyUFL^4WD?uv^lrysJ>mV^7? zWwFmAvJn|7lH&}B4h}OI2u$)ANjjTAdMw# zFG^fM6@V1=y3_*rDF$MsFONywtI_Cv750UV>_30J&MU?7(xugD=n8;Ca(| z95XLWKQtowD!kdtAonFa&n#?0@dXXc{4G;iXQYZ=#7KgYO_JhTMj#bcq2p*t^zR&; zWTpAxlIXo0F51FhMEP7vftKKtNec6z56ucZqeWRM3x84Nw~<24+3wPS6){_@n$*jT|Q z+6YJqC4#BaHASUTIbRD_*RJw$B9y_na#eyZ5vz+DbKX)!ZOg5OOe2a_Jn` z5@IbBge?C$ppQ!bp}b-rrto<)O>=&_H6!*ZSV!j&kAz7_3l+xy?1LH;`+ zM)JRp*3Ry>PX7-awrpo;{)Z2PDM$+bf77A@@w5N&9fC$ib}qKgAe-+$QLw}$D|J+L zG~fo|PX-5)&~P=dSSu6?Ff^;Fh17#e~rwZ=0P!NS@90be#2GqWkr|b#9#X0WThJ{XQs$mgfEr2=>v{l+_CR`jK%Q zc8nq3-=@03m4?ECv*^?ooQr4>y|IvxQSqfF%7W$#QfY2=xYDMc>l$^3k}K9!fF(Gw zU)v6sfc$z>6ST+)G9}#FhQ?Nl^jZ-ro574sS!Psi`J$$H#{JK)WX!e4VIoxN&f7&! zn*L`6QO2eNG8@czD5AZwR8Z`Y@(WU2wa?A*6ORr;fh$0pbh%YenVdAnOp6r_)f`gm zSqaSNJs@DYIdUv5z+CngXP}?M-ueZlH3n_apx;+P0xsT)O)nI zv~(wac9j}#Lz+vv?;1p%ca1d{U|k{TdCL>$(w=P&5eberFM^t4P!@O_vX+^j;=Me^ z`_jEi*R+JBVMd!;>saQ@c~oWU`gj7BvLJU#t+@bl+TO9kUdc|sb8AgXB#tBi%Ho)O zDzOW({`tfawD>ElUj5^Uc<3=M-a#>s_3|p-Wjio@J3aeUol}>jSy!9X`1(7g;daj6 z5$6xX_f) zQKOmFn?Tzs_7JFtt+)!fT;!;U74fUdm8Zc5N+_lIOG2LF?cHElf z;}7L-^N>n6PtlfzzSy{z5O%@7tF#HGr>5Ij{xws{1N-pu$uoK_^LN5N$$j3-4>Y%9 z)$HsMsq=}Bv;}QyMd^KhW#(+3jJM9V^{p*O)`m&F4b?WIbj>!S`Yb1^{`oS*OQmKN zj2|v0(l_sMa0*vb9&=K?+f}sNc&~2DFmHz+XbH?pPm88SSrm}Wqu*e5=~;O4eLsqR z6nuhf5Duh)&tx z#6;DwFO0DcP^US)Lc zWr~Wo83kPG;;caG04kBP*~GFh^7E?dE(r9aq-SI2=tX>t1NxsIg~2!IuNFl+B{!i& z-he;L!TBk!;)ynBE&#FFD33Ya;v#QFKaasdKfof^?(+j-te@&{VQ_w$tLD{`mA}_e zampUF36Ly-GpGjsZ-%@7s(-@fCPr4m09&K~@xl0~3C(P!ZX3L055bM8DkL3J77^y|!O!7kmG7Ydp#}RkK z?d?K_t8*krjT5ve5em4ew%!#X2U04?H^sf;jxdeuOD?+L1dp6j(2z6vsLt4lG%x9* zDoQS}V>6$S!aZZYe3>mScbYY8YmlfpD#1z{2BEhbX%8^E*^z0$op4Z0lG4 zK*c)5%C8x+S<+c6eE|5Kh8f5K5&e9g9DpvN*PA%;;+orgU-rqhTS<{EU7vn?Z(syB zxRI{^vacX7*p4h9t&^GOXxq&8!(Z{MTaxyI7|=@rD3IO&^MBZ6{}~`o=Kt)ED%#4k z3dnDA9}!9^*}>@D!62*!q18$#*lT}w!|R!zTx@Df#IVJYWflyK+Fc2HmoW1^e0))i z_WBi&dDkGzoI0KrfBx)RZ^rKT_V$EefKJb{+Gh>VwZ}5H;|s6;9a&GQ4;*9Q%AY~H zmj=$LL__iNJ7JqeyQ@XIpd?8Q_7js{G&4N@GM%3)U4}isRTf7Bv*&NkA}8yoCXGe* zXDJVE1BPgtYJ&&Y+5`K(D{tF`PBagLjJ9?1MGBvy6@*BcEbU@!=AU*9<{r#TwC*O& zDhMypgmTq@WU29K%8_s@W*{L@g^?FZCo2V5x1fz?$pUSW}R@ofEm6|0*V& zlxS`=a^*6jY==@{cvvWFbf0$%U4HAZ&e*t42nD!T>Kv4u{zaRz()$)~hg846#&^+*iS;*-Cd)4Te_H@SQbzx>#7I=L zPzPysbqM=^M^Qt+kCMe;)q=!aEtN==Ep4GE#3$8?%OVrKVSf~S{kH$mL$Dch^+0Ar zS`g3Hz+27ibk=b`J~nFe{_=W@+b#M-Ikq>L#M41>0D>(3pof&PtzsLtD*P}3dQnAZ z2!XM!bQ{AqVjBN*k*Gw3y?PKf=?9XZ}QRy-2i1GEbU8am|=1i9kb97jbs&u*7*0kC*{7u{ zzK+51m|0Oy>?xe>CG-X$$DT)`I`GGTE!hRtZEd)NG%c%FNf7|@JaR);>!QcPyulA(qwfKo^fVx;8!3Xm&o-u)8;VTE<< zYCa1tP*-l!di|-_iK|)q*cLg9l<+7De_4suY)Qg@!a1)g7pLy!EPNi?*-Wq+t77eTW~TIWhjmo$J82ksoaSMpdkF zX5c`|O~`1)Vw<zZ(_C5wxoJaPNk_GZw{d4_JxgKeR3h`~Oi;GMn$xmu3F@vsB! ze%cyEmIeIR;2#+|>xRRg8)F#P35Ed6RkK0x$br`__+-iv)Q29WB0yXlyjT6ss`YwH zNBJI_utButCjBU0_@V~WB|gFr+(CbHA$jR2%X_<|rPvS#_wx4dWGW&0Dn@>wf!*<3 zs6@+D+JR8;iGd>4lC-p`X0B7Blu+LitC&QIN|Lls$tPBcxO0wTkVNT}q%gSfPFyNV zy+BU7s?rAze?v$Lin!`D^2aGx-;1!4Z`U9HognE7%3f{VRTuE~nbHrdEvVWymwSw# zYB&2@asT~qCzqCr@>_CH%lZU*-1Z;HiUT9Mf@|NcUy z9vp)mDRmo4_}p(L2~-kpz505DC*4IEjUPV7&ZEsC-mC7(4{h4l1dG*#+q78gJ%7qI zQ^%{XwKY@)U*T4Dzuwr3bkpYFNZziO(~H@OrnuzW-MvDzM7nrAPrgjOi7u@75|uzb z|Jl^$>7>2sRMhstI;MmwQ6)?(*MSHR*qG4Itg<7`uBOZwehwR=_j|=r|8Pa)L49ja z+kr?Xfs?Al5lw-)cESM)7caerqscxwKiVrptEorf{axC)MD_!#&(^12#Ke6jYXowr zxL=3gKY}(?vv{LXawAbXG}F+6FSG?_@*{^(qU@QKDq5Lq~|AI@D$?2CnXJ zvn-iP>fy`t6A?bhi%!YUD_i`CCG6{2`b~J(U}WV?oad93#C98rX+#`B`m}#N6$6u| zfi~>;YfT);V^DU7euB$X{M(E{wn=~*+9-})_{;fzZjh!H_8tTOX2}poB(pL9`_|9f z?E#S&@CovrNgwRqYsLq-k1xbnuUf3Wukfw2gaL%S|m2G=}4s*Q411K zq+2s624uc7aevAt8IXx%Viz1q)O(xX_-j9r)xzT70tH_&DEQd^!+A;6$;i>p?JpDc zKSw4+3tSv!*!7DlXbJ5EgI0GppkOMXXa{dMt$>mQuJO_E4+8ZI^ zxaE`O$2)HQyOX{9?Ch=&726gV><-d_z!lBao=70gnG|#S0N!4qn|vB1IwZO%aLh@2 zsYm)#p~9+>giV{v#P{l@fb*bnpR@TfpAe#b>M9d1uOhQi7d#orbDQj3o!Zr+t>wz3 zK7`TRme1Z64jT^?tHJ-I`F|aTe+I!PF;_^1v=fA{fC$c{L}F1(~3D7B)Vl~*Bxuybaf4vu@v>+*%B3)9(Od%5(Sbiz5Bi56)Me>RN=gXC#KaeL-Vn2a;(KmOPk! zuKa^<)V=n(yi)~%YO+!(_FoufjVU(V;ekhoR(Tt5|9EGMBYoK;!*8tk?eW~bzNfqH5%a#z!=Lx z(@j0Xe;tkgKHh);u2~Hbz@=brj@uKEw*&b-0u3)JFd6%t2vYE~b4euE1Ze?OXi`vO z0T*+Z1z!n)JuUwqBRt)`99+SnByM|~tGwLZb4JG`pINo<5yZdww^uHPtEq+f!r;l^rlQLA(~&%m&a;T&788w!P7`|QX(tsMcn&)^xh(!# zE`?rm*2#T-KZBO{v*EV0S$hxZY$~4gC_4U;=@PsZfeU-34OBsK!5g~g z=7g+|;WSZFG2?dHTcKW~6*a47Pc8M;j$%+#LK&@;{^|^4i;hw? z$|~EzNR?o^Eit6sbDaKjHI~GS_ZKXNabL;S9VMogSff5^Q51QFnd^LMTTx2$1I>Ql z{&g?)PE_u8EYPIFoFia}D$D!w%h@Fbt$0#I-6sPPID zaPGiKw(49zMQ&(TPaBk4VJ+{%vQ@T3}_wdbWQJUjwQSA4iw=V~% zpNX^r*%GV{1OqGOX>^YiLM%I}Zg-bl=o_|N7sI&L*1xi?r1kkWr3YkS8rCCtky~cw z!`Nb+s?_H83|4g(FTuHS@=b{?7T`ZC(lB^a#j#%+(wygfhxz4ZS$xzy!iKl%#_}{E z;v%=Ox{qRf2cl!lwoiKaDbi zxFgjtKKgm2*(|o>cDGm$%;|gSTaZe_L4EsA(OdC?C&tLpd;N%`7^z#c!Y8^gUxBjh z??ag<|Eysy%Eu8V&l2k#abFGbv(=6sPj_nd&IY&hZKRWM|ks{{DIcVRwoVuV9 zaYfI}Y7%d-g36nK^43q`ucBY64XOA+HV3tK3=GBwNG0Ru8b z8S8KZ^85L{eqspu_!%`Nk_h-r^u>TGob9JKEA2L+>B9~UyA#n~ZMS+%i^teFs%@57 z4OUOww<6N3;>gW2Ikytr9E>{`VX(V*%oymdZsEJxr zxRhnZ@eFGVa&oSC)mg*3>)oK`EAc)aX5)Qk9|Z072Gvm>X(f(lcSV7fT0?SO-tt4w zXzb|ZZf-D?4n6j$$UXBS!kqar)6~XEzSc1XN<*To66ir$!klvKXzv;uj(TRaTvF|D zf~r!T*>U2y&?A!r2GU6yupQRm@-oXdV10++QJ8!8>VsT}9D3%ae>rw3lfK8j)~h*1=^3z=R7o)`nwUYrF|YXfB=l;h7o zzSjiXz|dcYr)NUDlAaI_5a>y}2R5&sIK^Wy_^hpnkt>VGHKFyX&Gq)EU)YE>>n(QH zMUKI%W&Pr+yIb={3CJE%y>slu8g15UrSr`|!+ff9M|p7g znAi{FLPn&jc+~TTdJk{(p4FC~CRKv_DhK^8mH=tDOB_@i=5Dr6sesa)+fNxrSb2W# zj2H575NU#^#@q)MU~F4`DzjE%uyv>jd9cHwctAb5isdd(^cX>Kv#J(Los) z;so)XW;n6<`_6Iojs0?@=L4h8C+(Kge7h0is}7lsv+}OM_P0m&SiezSxB46(V}?#$RanO}^P8P3hWGfj?Mc5#P9VqUZCKAmrL(rGy;aiw3_cbhs#dY}pS)ftl9=8JdLS+$%Ut@?ZYV$KtV>1H?4#SbgD9s+d+9ZkJfN zbY&%s7w^`PnWhl==&<-O^lJX5?yjhKl262)Ph=}PM+LYDecB}b3aw4r#IvD_uygV1 z%fJ}p)b;9pOD=@Io?C#%sP&@ajGZ_oULvN@f2+D^6%E)tsn6Q83n1=6lIEVq6iU= z@dnQQSfpOPcL`p&Dc@=5=Qc(!vNLuTmJz_3=@~LHSdbak(avVvfL=Z?uYcPH%JG{K z*Ff9A1_(Xbz^XORg#EU3xzl>unUm<6#?1I-NG=@#@T+)E9ja~;+h5Zq#WFr!Zx=c+YA zGICjMQ@p9u`8HjJ_$8*LyjG=-N_p4V`hV1DoPWVZ>@()EC}dsvX{@9pt;M#udJPX^ z(at^@TApFQ%8IY>ac$p)kGmw#c7pjPF*@M5}!5|2|}lFgwp@opPp<5F{vV z@A|k;!ybXoMS!wNZ#*yU8o%sVW+bHak8q z$SYB#wZ5+uL3vQ!x5R-t-BoH06~fTGvq`&wsB0cN;XHL@TU9m85OHx1U!`cq5K;BS z#rR?_SNTE@6*YYLKDHe`Juz1Dhn+*=2#$G<7W)jkRKhA(wfWVAdhHNTKHY8kDLDC? z{-z$1IpWaNd7}kmVJb}~`5Cs(`gxJs5^dVRmy792v}|H}a~U_-p|v65C%llazT*bY zlq(h|Im?$H{8pvF0Dj%vk3W2*INdxSe?>ye)LQ@ zPRD|!Z=EU|U#FWTZg~$94{+&o6OOeDpZH2UCG(IxGP=5Q^uN(3Q}Z9b8YM&PB!K;L z{8sft8SHBX6jshX5jvAfJ^Z{LGB_4IiG!4s=WwCyj#37WkX1<24V5({buH;)96of%Teh#nRS$15!PCd5 zd`~Xo(P-Lg>)<}kNy~j7mUixXtM})PjrR}kP<|93`o5?G;ys#obo{QiB8pll4b-c3LKD!v4=WxmKylmg^)?gi! z^(F~jYDME*Oou{(A69EAUw)+)bGch!bK;spq4)q!gH82#ekak~2sgO~_&epgT4xkx zUy(AS&s0Gqip^9rvr4U5Q)kPylr3uGk83qr>glt$6sc6pRq;+Ar9~2`yg4T<>qL`WvCOc06=qzUCiP0@ z87H`+P18ohuX_2wxdt1n4owDyT~p1Hr@W67*{IjN=U&zag#o9O3$4NqqIWK7Gp2UV z;O7_QdqOQoh53!d057plCAuMYj$*StI+Uuv-GQ# zQ&roo$mED?_@!0t#0=3%dFWSa_CMFE0QC8zA19gHYMMIWs1Me%%&31t`3t&o0)M=6 z#q^hcsDeviz`t2{B~`U#$(AwjmhJK_7HG0*8s*2Qit5$<_IbqfjcTUY^T)u-fXP#@ zE8+_~Oqgu|+?<@^IT`RLcrDXVyJAS= z)IbCW%Xiu|vTbrG_=$52?uHm4^63^;$OjJ&ykoVSvCCJfL?7)4-T$pXA-g+HfWT(6 zMc+@VM1L?`pqkCTx0;`LPXF^D0cyV=o56dP=M#5mi&y1$U+Y5uX1%8m`?}qSMe$Gu z$2f5;6WSiS-*7N<=^*mfT@}^M**Z$Fa>-swN(JT+Fwrsd$V3%&@xE!H<;jIB%zjjW zd8%EA;35^$g%zo6Eioxu*PFBWY)OWETNUAnbRH4$IF`*fQ^AnRhkPUs@x+2`2NwXt9Ank zHpN?c;+v-C<5AJmtnks6Vl%i>B8k{;rlohIhuFz$y0jwwbij2*TrhwZR;|wOt*f--=KOB_B zr+`XU*)V7=%ZfDL(6jeAptaxs6IvtG!c|EUw=|)YIxTYneV?Y#EI~f$by+Ec{-&8p zN{3haC<&EUkye^LzsQmV6Hct!a3DQ;`t^G=F_0|o*c|j5oYyNoS4YR7&aAj@548HRgLwq&CX0&tEZx#qg{;R zPh|XM#bu$a*oqaS<~_hrS#0@QQX||+;}ZjE5t%`!laZyqs?e55Om|8n0;sVchI>5UkSl%R&|R< z;|>c&4l`-#G31l9`SkXsS@p4kMw%WB4)zqmT8GJgOMNQ~otGnJnO8>~p=)*b=z}Ut zMox5?ex>hH^Kke?%Rz+h5~}DYDvu}%S4pBn`T^Jx$(~sFyT5$E3$jbj?N=3rW`@0= zk9mIHg6iN)Lwa|uT+i7f+#OD(>8N@|=dbCu7zJKj4B)}e68xQ2fWTTwqBZXLo`NuO z4&VhUD7%ES*a6|!@TWr<7NMX>M4VwxJg#X`c}vfO2`d>)3kW)e=ToKpb=|Jv-Fy2- z7d&6o8G~foeIE7&}kAat0`EwrGi_OTzEyz3+p)+F$r?$`;V8@Q!OdIP=Ty{yNEq3_GzI&yHv$5rsT3O(L>ye6X z+(O(}2G9SqrU; ztN-2BxO{%D{iW{~VYU*BwOp$)7|_NFcz{yf!mh@#??ryO%=0{0GGMlYj6 zj-&l7EHwGFj#!(q_fVOz>P#O_D#$_91W3U3$0MBT7MCHjlw-9XsSmJ-*=Gnw66(jK zD@^CGT!5nV3!4>M$U5Z?0TuTW3;5Qm+q9wz;|^r=Nm3yun%@{G_s&h!cf!O)?Y&w^ zY#X}NDge`!%0-!4%i+{ah4HQ68!Ecj>mMZWv0sh0a346D`4mSyi* z%zOj+skO#RevxHlxsL7NEm0IhEMMUrMYYB%)o_sbQ#?|MI!o8&q3=UkM^XR zQN4&-Dohpia2e4F0G?-*mu!i1&I$QleA&X`pxvNSAJi+7{)lZzrb*f2?bmAy^4geH zhz0@=-llB^y3`n1*RG`B0Br)^irE{jeJS(yHtyPa9}&{p-c$%ZfpNN^wVLY~!FEO) zvG$SYOWqf>v?V=duK>NR4w2b}Rf9#8j$;ur9f=D=lqKgEpD<^-)bt(dr*jjuD=REx zO%5@K3^ny>acqW$2X>IvY)9@7q#;Vv1JtS9E#yw5Oc9L{#SDb zk&y(@-h^s%NmuRk6u>AI6apZrMnr3sB9cZUe+Gg~)odEpoYT;HHhu>_D42O)Kt1H+ zO%_!yuvi3UP7E)P-}`vEPI9LIdDIQ)LpEi^6r;~095W(}{IZI^rw1LO5ZsK`>(d|9 zOfweFP~O{b!t=eBjIbrwY3)}Wa!SM(=>r)oO|o42N~b1$x{R8cSl77X)Siae>8l|v zNz9#J#>I)VvM^SMk%|h^p0z1vmV*?G^IY^y%CFr~F*=PC2a~e53f%Mzwxo_Y`!v}! z*C%a3SsA8h8R)lhriY)J^WBLF$8d`BoTkZq0A*GQF1DrBZmo@Y#GIVUs>uu+aiZmW zb7-kcmKo-Pl?Dl|q<}V3s}-?IIEU=dVZ;a-mS~d|=e#rxDDULX8bX^|nYUjVv-1Z>9ER7<@^kn%N^o0KR_S(HnHO7K~u z5|m2=aE$JyU!!;dcfp+Bk>9&u^HmxNza+BQTBcf-(sK5Y<$F#ZXKSdL{Lo>*-4Z7e z@!4uJuQ-HQfte1gVk<7Dl`f#(F0Y|5it=GwYgo|E+^si7$VB@XPANc2($)(nJD?gI zUWM?(Xims0Yg5ePotAf}y0i2i^>#g`0b1SQxSiX)vAU~UT89Mnlq=*ct!*bYfGX#U z@d)!zv5aafY6Y6vw&zY1=P#y|*eT0V~AMvqBaEr*N5U^o^Kb6Zk;EjT^P{bJ3WsUc`ybC+}OXs<+d) z-$yW^x+W9-@Y!`9dSH#oyEYQ}qtoeLs$hlW-oA;yG+VyNLY&mYhCN_XLF;os0ImI} zsY=Mc{#Z%Lxi_Sar&AJ)J93pm@RE{UR@!OVA(|Ie3Rkx5SGN3>6u$J3`Zv%Clp+5k z6hZwTri;CkiHot_|3i*u80R6aRDA(abzb-P)tX>@ z9utMDU|nE8^WrxAavJS}>(c6u-rABAg=5uT8nE8Vy-DXjAS?&)43En?Yjc#fX343; zt{ZdQlZxC(~O zXVG1l!tj5)D}+`XP0$$|3L0rvMuZOmP_lW9aKurvb4jZ7UEn^!G3`nvqDYgMasd2Uq*x|LC4rPS(;tf~~aF#8!R2c=oFsQzO{0dP+ ze#?IqW|Nh-P!%#8o^9h8+oa(=Y!AQYjdmmeUAebc_@j-<`FM%^nv&lkq|B-l#^@Uv zJvaouA0q3V1b9Nsv21H112 zcII|LWh`9=g{c9kL9qXKVG4T1A!hPV1?xnWe*mp-Nru8J8WfJot)T%8IS^8%m~>PW z0cu}bcpor+LFU;g#iP-84MSamO;2^g@@t3? zyc^?Zag;+Wrj*DXs-mD)^3~^F8MyobhCt2QSaegllnjvTrU&pK4}f#VButXIY-FzA zD3y_0Z;;|$ueQ8@7u~5}lz0}PIydUoW&^#UZ|xQXil{1u2C6h0m2#6RblP;QvwbSJ zhWn!1>A6+;8+QE4qYJI!nWonE!AEf6BMCRyAI?8dZQgPR$BFLa+(*CDKqZmS%6<+i z6$c?h<)^kOXF9Hec!Z7>$=GB@2a1$QIOSDOq3TQXglzk1Q3!woVz3>hfbX<4RF)QG*v_2#i0B$0>GCf+) z8DZ2o1ty@B6{yG7c@Z}_t~J03w?RnQwi6|=T*TB!q&%>fj=LI1>dE`1%*S~pP?%u> z?Yw()H*SY{AxPLm)Z7<(H6t@dZ!wcgB~qn8D_^_agYKc?hSZd{ku){4^4-*|+`_dN zjVwDKTiar6DHwft9|yhl!5v|hbdc5YC*=lvZW)HJ4*h~v0k&%aqg3`aNxwX#PwTWO zo2cFwo10J0GQLpH{!OT!cEaq-9K6A*-@93}#W`+rlC$7_4(?g&%vgwu&EKEoiH|DF zmEJy7J-?8O{LothJjQ=JugL+UN=nZ!1`jOot8=ydio+#pQ*7mJlog)b#R8`Qf{$nk}F-Q8F=eu?9Fw zn|S<_)~!5h`-ed-Y6yn|KJ4ymQ3I(QtP5of0uqdW8Bre5bP1fRvY9y)9`{wgLT4DH zi6RMx_XmRD79(wg6E(&r7oYv3j2&*XD!;dD4aCC0 zcAp`FWq-UFT>!W5*AsI)8lmToeZPy717co1bGy)k#-(W8FCgM@a>$61&-4(F9)85&I;jnu*^mBYx4jVPjCi;^O+^aTuzSk-gN16uNmQAEz)g z#z3OduFg#}0&=bLLPSxU?N|CytbyF`Hps$u;AY77^uOgud}08t(1?(k3Do>yxwJpr z(e}1Jq7c2qZD><+GD!xWwCdma5J}_r>OkHPzj*s)&Lpo(Z6P`ZsWuiBv82%eA04f* z0Z}28DhL@(v_!yL;vUG`vX7-vMsYr>s!iKBhDmR0WOJ%e`LWCta??j(mI+|v>*_Uj zC8x@Ifs)fX?9ipk3q@lx4jj=Ip3E8D!!kys#ku%7Z;vrz#HI51BiTKreUC$(Xb*dz zUuLo285dp)PJ?1-WW8VLl+Hc3cI9P|ypg5{+`#I+bJjxy~Al-70gJh1s&Iij1E zXy#p}do%DEBqI5KBQRNZ6EH?V4L>?uncct1eP;Vd(KUdK$!`fx#hTc5MXQ$>L>8tB z=Nyx!rh=2f7QUcn_7IIQM=UUG@YtJ34RwdJ>AD<~^azBaBJ{cdKnLVXN>!Cf9HN*8fM6BwX zrSLFhn4Y8_{tDpk1iHbe?TBx<#JRJ5U(lGoI$_$tc++TWYkTP7U{Rs5oT@Dl z?5hjU0P?7@R2a$*@FLt_3iJtANZ02AP_<`x3^n*}kxT7}8Aw+c@bgb#M~yX(WL-Jd zipm~(skzuY(q>cjh=|h6SSd@2#3c%M`v@#4Aw@E@`*{@fW?o7<|krHQ8@x4*?5qFP|L~3qT zj=o5)!jN2|MZ8d@3<|77VE^pWdkp&~=I>C4>Z~Ok%40zDjDG?pH1sLre7}BwVbATnp0~He z>nQCD8QOcZn8|DKr@?41=pyfcLsO*)0Z(=N#C2)P#ZL;9BIu`uQt*XsXUc0A*LH7z zb1v56H7gzk)j%K6vFSf$#;8~rS(!Nh^>}Xsvb;d{ZBq9-t^FAhP?D1uU?a&f^Fg15 z?2|Bw#kU~1jpSoX^(wFNHPv8!Nbl}`q?ZqV2@ZE!lD7=Jbji!9!#tBePEIEE`Kvxu zg&eBr2JRPPbyaa8CvBHpv1S#s}H@XT+JT4&Oj|3xV5Ky57v3@e&(Y+mGyizSZ+ z2kGJn>qCSPDGh$%h>+ACfR8F7a9x#fY4>-2Wr(wNoJp+ps_3i!CEGb&ZM3NTRx8sK zbZ2srmYY#)1z=<_~r@ueDtF^6a#mm z(yp58kmJES`~3OiJGbs#otWa323s95UKrDk{sg=GuTSTmxJgWyn0}SFR zhfi`!_`;@(9AeC|&Wcn1zCwMyTC}zU)i!TXZTm078h(dUkVnleTh!mTNjo1-RbA~hmI?W8`$i_eV1B;AYQC@Ng0 zu)6SF&&^V&&p>p^yS%llZ;fiDbavQ&pjN{ty;bNmu&-eiJqzeK;CLsi&Vu7&s}(&e z`∈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 literal 0 HcmV?d00001 diff --git a/ripple-core/.gitignore b/ripple-core/.gitignore deleted file mode 100644 index ea8c4bf7f3..0000000000 --- a/ripple-core/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/ripple-core/README.md b/ripple-core/README.md deleted file mode 100644 index d89d96f5e8..0000000000 --- a/ripple-core/README.md +++ /dev/null @@ -1,391 +0,0 @@ -# SerializedTypes Overview - -Ripple uses a node store, where objects are keyed by a 32byte hash value. - -These keys are created by hashing a binary representation of the whole object -prefixed with a name-spacing sequence of bytes, unique to each class of object. -As such, a method of consistently producing a binary sequence from a given -object was required. - -Objects have fields, which are a pairing of a type and a name. Names are simply -ordinals used to look up preassigned names in a per type table. The type ordinal, -similarly, is used to lookup a given class. - -In ripple-lib-java the type equates to a `SerializedType`, with types such as 32 -bit unsigned integer, variable length byte strings and even arrays of objects. -The fields have an ordinal quality, and can be deterministically sorted, -important for consistent binary representation. - -There are also container types: An STObject, short for `SerializedType Object`, -is an associative container of fields to other SerializedTypes (even an STObject -itself). An STArray is an array of STObjects with a single Field, mapped to an -STObject, containing an arbitrary amount of Field -> SerializedType pairs. (See -notes below on differences to C++ implementation) - -## Types - -Following is a survey of some of the classes, sorted somewhat topologically. - -The following json representation of metadata related to a finalized transaction -can be used as a concrete example and will be referenced later. - -```java -/** - * - * # Transaction Meta JSON - * - * { - * "TransactionResult": "tesSUCCESS", - * - * {@link com.ripple.core.types.known.tx.result.TransactionResult} - * {@link com.ripple.core.fields.Field.TransactionResult} - * {@link com.ripple.core.coretypes.uint.UInt8} - * - * "TransactionIndex": 0, - * - * {@link com.ripple.core.types.known.tx.result.TransactionMeta#transactionIndex} - * {@link com.ripple.core.coretypes.uint.UInt32} - * - * "AffectedNodes": [ - * - * {@link com.ripple.core.types.known.tx.result.TransactionMeta#affectedNodes} - * - * { - - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - - * - * "NewFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "Sequence": 103929, - * - * {@link com.ripple.core.fields.Field#Sequence} - * - * - * "TakerGets": { - * - * {@link com.ripple.core.coretypes.Amount} - * - * "currency": "ILS", - * - * {@link com.ripple.core.coretypes.Currency} - * - * "value": "1694.768", - * - * {@link com.ripple.core.coretypes.AccountID} - * - * "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" - * - * {@link java.math.BigDecimal} - * - * }, - * - * - * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * - * {@link com.ripple.core.coretypes.AccountID} - * - * "BookDirectory": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} - * - * "TakerPays": "98957503520", - * - * {@link com.ripple.core.coretypes.Amount} - * {@link com.ripple.core.coretypes.Amount#isNative()} - * - * "OwnerNode": "000000000000000E" - * - * {@link com.ripple.core.types.known.sle.entries.Offer#ownerNodeDirectoryIndex} - * }, - * - * "LedgerIndex": "3596CE72C902BAFAAB56CC486ACAF9B4AFC67CF7CADBB81A4AA9CBDC8C5CB1AA", - * - * {@link com.ripple.core.coretypes.hash.Hash256#index} - * - * "LedgerEntryType": "Offer" - * - * {@link com.ripple.core.serialized.enums.LedgerEntryType} - * {@link com.ripple.core.types.known.sle.entries.Offer} - * } - * }, - * - * - * { - - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - - * - * "NewFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "RootIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * com.ripple.core.coretypes.hash.Hash256#index - * - * "TakerGetsIssuer": "92D705968936C419CE614BF264B5EEB1CEA47FF4", - * - * {@link com.ripple.core.coretypes.Currency} - * {@link com.ripple.core.coretypes.hash.Hash160} - * {@link com.ripple.core.fields.Field#TakerGetsIssuer} - * - * "ExchangeRate": "5C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} - * - * "TakerGetsCurrency": "000000000000000000000000494C530000000000" - * - * {@link com.ripple.core.coretypes.Currency} - * {@link com.ripple.core.coretypes.hash.Hash160} - * {@link com.ripple.core.fields.Field#TakerGetsCurrency} - * - * }, - * - * "LedgerIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.hash.Hash256#index} - * - * "LedgerEntryType": "DirectoryNode" - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode} - * {@link com.ripple.core.serialized.enums.LedgerEntryType#DirectoryNode} - * } - * }, - * - * { - * "ModifiedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} - * - * "FinalFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "RootIndex": "801C5AFB5862D4666D0DF8E5BE1385DC9B421ED09A4269542A07BC0267584B64", - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#rootIndex} - * - * "Flags": 0, - * "Owner": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * - * {@link com.ripple.core.coretypes.hash.Index#ownerDirectory} - * - * "IndexPrevious": "0000000000000000" - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#hasPreviousIndex} - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#prevIndex} - * }, - * - * "LedgerIndex": "AB03F8AA02FFA4635E7CE2850416AEC5542910A2B4DBE93C318FEB08375E0DB5", - * - * "LedgerEntryType": "DirectoryNode" - * } - * }, - * { - * "ModifiedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} - * - * "FinalFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "Sequence": 103930, - * "Flags": 0, - * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * "OwnerCount": 9, - * "Balance": "106861218302" - * - * {@link com.ripple.core.coretypes.Amount} - * }, - * - * "LedgerIndex": "CF23A37E39A571A0F22EC3E97EB0169936B520C3088963F16C5EE4AC59130B1B", - * - * {@link com.ripple.core.coretypes.hash.Index#accountRoot} - * - * "LedgerEntryType": "AccountRoot", - * - * {@link com.ripple.core.types.known.sle.entries.AccountRoot} - * {@link com.ripple.core.serialized.enums.LedgerEntryType#AccountRoot} - * - * "PreviousFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsPrevious()} - * - * "Sequence": 103929, - * "OwnerCount": 8, - * "Balance": "106861218312" - * }, - * - * "PreviousTxnID": "DE15F43F4A73C4F6CB1C334D9E47BDE84467C0902796BB81D4924885D1C11E6D", - * - * {@link com.ripple.core.types.known.tx.Transaction#hash} - * - * "PreviousTxnLgrSeq": 3225338 - * - * {@link com.ripple.core.coretypes.uint.UInt32} - * } - * } - * ] - * } -*/ -``` - -* Note that ALL field names are, by convention, upper case (in fact field names (index, hash) may be -lower cased but are not serialized) - -* The `AffectedNodes` is an STArray. As stated, the immediate -children each contain only a single key (or [Field](src/main/java/com/ripple/core/fields/Field.java#L138-L140)) - - * ModifiedNode - -Moving on. - -``` -com -└── ripple - ├── serialized - ├── core - │ - ├── enums - │   ├── LedgerEntryType - │   ├── EngineResult - │   └── TransactionType -``` - -* In the json above look at the [TransactionResult](src/main/java/com/ripple/core/fields/Field.java#L164) field. - Note that it has a Type of of UINT8, yet clearly it's represented in json as a string. - -#### com.ripple.core.fields.Type - - This is a simple Java enum(eration) of the various types. eg. - - UINT32(2) - - This definition implies giving the static ordinal `2` to the UINT32 type. - -#### com.ripple.core.fields.Field - - Consider the following definition of a field - - QualityIn(20, Type.UINT32) - - As stated before a Field has name and type ordinals, but it also has an - implied symbolic string representation (as seen used in the json above) - - The string name can be looked up via a `code`, which is an integer created by - shifting the type ordinal 16 bits to the left and ORing it with the name. - - See: [com.ripple.core.fields.Field#fromCode](src/main/java/com/ripple/core/fields/Field.java) - -#### com.ripple.core.fields.HasField - - This is simply an interface for returning a Field. We know that a Field - implies a Type and a name and there's a set amount of them. For each concrete - class implementation of a given Type, we create a XXXfield class that - implements HasField - - eg. - - ```java - protected abstract static class STArrayField implements HasField{} - public static STArrayField starrayField(final Field f) { - return new STArrayField(){ @Override public Field getField() {return f;}}; - } - ``` - - Then we can create static members on the concrete class - - ```java - static public STArrayField AffectedNodes = starrayField(Field.AffectedNodes); - static public STArrayField Signatures = starrayField(Field.Signatures); - static public STArrayField Template = starrayField(Field.Template); - ``` - - Later this is used create an api that looks as so - - ```java - if (transactionType() == TransactionType.Payment && meta.has(STArray.AffectedNodes)) { - STArray affected = meta.get(STArray.AffectedNodes); - for (STObject node : affected) { - if (node.has(STObject.CreatedNode)) { - STObject created = node.get(STObject.CreatedNode); - ``` - - This is implemented by overloading get() - - ```java - public STArray get(STArray.STArrayField f) { - return (STArray) fields.get(f.getField()); - } - ``` - -### com.ripple.core.serialized - -#### com.ripple.core.serialized.SerializedType - -```java -public interface SerializedType { - Object toJSON(); - byte[] toBytes(); - String toHex(); - void toBytesSink(BytesSink to); - Type type(); -} -``` - -#### com.ripple.core.serialized.BytesList - -A dynamic array of byte[]. Used by TypeTranslators to avoid needless -copying (see fromParser(parser, hint)). - -#### com.ripple.core.serialized.BinaryParser - -Responsible for decoding Fields and VL encoded structures. - -#### com.ripple.core.serialized.TypeTranslator - -Handles converting a SerializedType instances to/from json, binary and other non -SerializedType values. - -Has methods like fromHex, fromBytes, which delegate to fromParser. - -#### com.ripple.core.serialized.BinarySerializer - -Responsible for encoding Fields/SerializeType into binary. - -## Notes - -* In the C++ implementation of serialized objects, an STObject can, itself, be - assigned a Field, which is stored outside of the associative structure. - - This is problematic when storing as json. Consider this pseudocode. - - ```python - >>> so = STObject() - >>> so.name = "FieldName" - >>> so["FieldOfDreams"] = "A Kevin Costner Movie" - >>> sa = STArray([so]) - ``` - - How could `sa` be declared as json? - - ```json - >>> [{"FieldName" : {"FieldOfDreams": "A Kevin Costner Movie"}}] - ``` - - This is in fact how rippled works. There is no 1:1 mapping of STObject to {} - - In ripple-lib(-java)? there is, and single key children of STArrays are enforced. - -* Ripple uses 32 byte hashes for object indexes, taking half of a SHA512 hash, - which is ~%33 faster than SHA256. - -* Simply using google protocol buffers was considered inadequate [link](https://github.com/ripple/rippled/blob/ee51968820fc41c5aeadf2067bfdae54ff21fa66/BinaryFormats.txt#L16) \ No newline at end of file diff --git a/ripple-core/build.gradle b/ripple-core/build.gradle deleted file mode 100644 index 7ee498ed2c..0000000000 --- a/ripple-core/build.gradle +++ /dev/null @@ -1,52 +0,0 @@ -apply plugin: 'java' -apply plugin: 'kotlin' - -description = 'ripple-core' - -version = '0.0.1-SNAPSHOT' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -dependencies { - compile 'net.i2p.crypto:eddsa:0.2.0' - compile 'org.bouncycastle:bcprov-jdk15on:1.58' - compile 'org.json:json:20171018' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.3' - testCompile 'junit:junit:4.12' - testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5" -} -buildscript { - ext.kotlin_version = '1.3.0' - repositories { - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} -repositories { - mavenCentral() -} -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -task getDeps(type: Copy) { - from configurations.compile - into "$rootDir/jars/" -} - -kotlin { - experimental { - coroutines "enable" - } -} \ No newline at end of file diff --git a/ripple-core/src/main/java/README.java b/ripple-core/src/main/java/README.java deleted file mode 100644 index 0d01f2dfc7..0000000000 --- a/ripple-core/src/main/java/README.java +++ /dev/null @@ -1,206 +0,0 @@ -/** - * - * # Transaction Meta JSON - * - * { - * "TransactionResult": "tesSUCCESS", - * - * {@link com.ripple.core.types.known.tx.result.TransactionResult} - * {@link com.ripple.core.fields.Field.TransactionResult} - * {@link com.ripple.core.coretypes.uint.UInt8} - * - * "TransactionIndex": 0, - * - * {@link com.ripple.core.types.known.tx.result.TransactionMeta#transactionIndex} - * {@link com.ripple.core.coretypes.uint.UInt32} - * - * "AffectedNodes": [ - * - * {@link com.ripple.core.types.known.tx.result.TransactionMeta#affectedNodes} - * - * { - * "CreatedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isCreatedNode()} - * - * "NewFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "Sequence": 103929, - * - * {@link com.ripple.core.fields.Field#Sequence} - * - * - * "TakerGets": { - * - * {@link com.ripple.core.coretypes.Amount} - * - * "currency": "ILS", - * - * {@link com.ripple.core.coretypes.Currency} - * - * "value": "1694.768", - * - * {@link com.ripple.core.coretypes.AccountID} - * - * "issuer": "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9" - * - * {@link java.math.BigDecimal} - * - * }, - * - * - * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * - * {@link com.ripple.core.coretypes.AccountID} - * - * "BookDirectory": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} - * - * "TakerPays": "98957503520", - * - * {@link com.ripple.core.coretypes.Amount} - * {@link com.ripple.core.coretypes.Amount#isNative()} - * - * "OwnerNode": "000000000000000E" - * - * {@link com.ripple.core.types.known.sle.entries.Offer#ownerNodeDirectoryIndex} - * }, - * - * "LedgerIndex": "3596CE72C902BAFAAB56CC486ACAF9B4AFC67CF7CADBB81A4AA9CBDC8C5CB1AA", - * - * {@link com.ripple.core.coretypes.hash.Hash256#index} - * - * "LedgerEntryType": "Offer" - * - * {@link com.ripple.core.serialized.enums.LedgerEntryType} - * {@link com.ripple.core.types.known.sle.entries.Offer} - * } - * }, - * - * - * { - * "CreatedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isCreatedNode()} - * - * "NewFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "RootIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * com.ripple.core.coretypes.hash.Hash256#index - * - * "TakerGetsIssuer": "92D705968936C419CE614BF264B5EEB1CEA47FF4", - * - * {@link com.ripple.core.coretypes.Currency} - * {@link com.ripple.core.coretypes.hash.Hash160} - * {@link com.ripple.core.fields.Field#TakerGetsIssuer} - * - * "ExchangeRate": "5C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.Quality#fromBookDirectory} - * - * "TakerGetsCurrency": "000000000000000000000000494C530000000000" - * - * {@link com.ripple.core.coretypes.Currency} - * {@link com.ripple.core.coretypes.hash.Hash160} - * {@link com.ripple.core.fields.Field#TakerGetsCurrency} - * - * }, - * - * "LedgerIndex": "62A3338CAF2E1BEE510FC33DE1863C56948E962CCE173CA55C14BE8A20D7F000", - * - * {@link com.ripple.core.coretypes.hash.Hash256#index} - * - * "LedgerEntryType": "DirectoryNode" - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode} - * {@link com.ripple.core.serialized.enums.LedgerEntryType#DirectoryNode} - * } - * }, - * - * { - * "ModifiedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} - * - * "FinalFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "RootIndex": "801C5AFB5862D4666D0DF8E5BE1385DC9B421ED09A4269542A07BC0267584B64", - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#rootIndex} - * - * "Flags": 0, - * "Owner": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * - * {@link com.ripple.core.coretypes.hash.Index#ownerDirectory} - * - * "IndexPrevious": "0000000000000000" - * - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#hasPreviousIndex} - * {@link com.ripple.core.types.known.sle.entries.DirectoryNode#prevIndex} - * }, - * - * "LedgerIndex": "AB03F8AA02FFA4635E7CE2850416AEC5542910A2B4DBE93C318FEB08375E0DB5", - * - * "LedgerEntryType": "DirectoryNode" - * } - * }, - * { - * "ModifiedNode": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode} - * {@link com.ripple.core.types.known.tx.result.AffectedNode#isModifiedNode()} - * - * "FinalFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsFinal()} - * - * "Sequence": 103930, - * "Flags": 0, - * "Account": "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3", - * "OwnerCount": 9, - * "Balance": "106861218302" - * - * {@link com.ripple.core.coretypes.Amount} - * }, - * - * "LedgerIndex": "CF23A37E39A571A0F22EC3E97EB0169936B520C3088963F16C5EE4AC59130B1B", - * - * {@link com.ripple.core.coretypes.hash.Index#accountRoot} - * - * "LedgerEntryType": "AccountRoot", - * - * {@link com.ripple.core.types.known.sle.entries.AccountRoot} - * {@link com.ripple.core.serialized.enums.LedgerEntryType#AccountRoot} - * - * "PreviousFields": { - * - * {@link com.ripple.core.types.known.tx.result.AffectedNode#nodeAsPrevious()} - * - * "Sequence": 103929, - * "OwnerCount": 8, - * "Balance": "106861218312" - * }, - * - * "PreviousTxnID": "DE15F43F4A73C4F6CB1C334D9E47BDE84467C0902796BB81D4924885D1C11E6D", - * - * {@link com.ripple.core.types.known.tx.Transaction#hash} - * - * "PreviousTxnLgrSeq": 3225338 - * - * {@link com.ripple.core.coretypes.uint.UInt32} - * } - * } - * ] - * } -*/ \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java b/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java deleted file mode 100644 index e46af9db43..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/binary/FileSTWriter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ripple.core.binary; - -import com.ripple.core.serialized.StreamSink; - -import java.io.*; - -public class FileSTWriter extends STWriter implements Closeable { - BufferedOutputStream out; - - private FileSTWriter(StreamSink sink, BufferedOutputStream out) { - super(sink); - this.out = out; - } - - public static FileSTWriter fromFile(String path) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(path); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - BufferedOutputStream out = new BufferedOutputStream(fos); - StreamSink sink = new StreamSink(out); - - return new FileSTWriter(sink, out); - } - - @Override - public void close() throws IOException { - out.close(); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/binary/STReader.java b/ripple-core/src/main/java/com/ripple/core/binary/STReader.java deleted file mode 100644 index dc3655073b..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/binary/STReader.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.ripple.core.binary; - -import com.ripple.core.coretypes.*; -import com.ripple.core.coretypes.hash.Hash128; -import com.ripple.core.coretypes.hash.Hash160; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.uint.UInt16; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.StreamBinaryParser; -import com.ripple.core.types.known.sle.LedgerEntry; -import com.ripple.core.types.known.tx.Transaction; -import com.ripple.core.types.known.tx.result.TransactionMeta; -import com.ripple.core.types.known.tx.result.TransactionResult; - -import java.util.Arrays; -import java.util.Date; - -public class STReader { - protected BinaryParser parser; - public STReader(BinaryParser parser) { - this.parser = parser; - } - public STReader(String hex) { - this.parser = new BinaryParser(hex); - } - - public static STReader fromFile(String arg) { - return new STReader(StreamBinaryParser.fromFile(arg)); - } - - public UInt8 uInt8() { - return UInt8.fromParser(parser); - } - public UInt16 uInt16() { - return UInt16.fromParser(parser); - } - public UInt32 uInt32() { - return UInt32.fromParser(parser); - } - public UInt64 uInt64() { - return UInt64.fromParser(parser); - } - public Hash128 hash128() { - return Hash128.fromParser(parser); - } - public Hash160 hash160() { - return Hash160.fromParser(parser); - } - public Currency currency() { - return Currency.fromParser(parser); - } - public Hash256 hash256() { - return Hash256.fromParser(parser); - } - public Vector256 vector256() { - return Vector256.fromParser(parser); - } - public AccountID accountID() { - return AccountID.fromParser(parser); - } - public Blob variableLength() { - int hint = parser.readVLLength(); - return Blob.fromParser(parser, hint); - } - public Amount amount() { - return Amount.fromParser(parser); - } - public PathSet pathSet() { - return PathSet.fromParser(parser); - } - - public STObject stObject() { - return STObject.fromParser(parser); - } - public STObject vlStObject() { - return STObject.fromParser(parser, parser.readVLLength()); - } - - public HashPrefix hashPrefix() { - byte[] read = parser.read(4); - for (HashPrefix hashPrefix : HashPrefix.values()) { - if (Arrays.equals(read, hashPrefix.bytes())) { - return hashPrefix; - } - } - return null; - } - - public STArray stArray() { - return STArray.fromParser(parser); - } - public Date rippleDate() { - return RippleDate.fromParser(parser); - } - - public BinaryParser parser() { - return parser; - } - - public TransactionResult readTransactionResult(UInt32 ledgerIndex) { - Hash256 hash = hash256(); - Transaction txn = (Transaction) vlStObject(); - TransactionMeta meta = (TransactionMeta) vlStObject(); - return new TransactionResult(ledgerIndex.longValue(), hash, txn, meta); - } - - public LedgerEntry readLE() { - Hash256 index = hash256(); - STObject object = vlStObject(); - LedgerEntry le = (LedgerEntry) object; - le.index(index); - return le; - } - - public int readOneInt() { - return parser.readOneInt(); - } - - public boolean end() { - return parser.end(); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java b/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java deleted file mode 100644 index 77f28eb7f7..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/binary/STWriter.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ripple.core.binary; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.serialized.BinarySerializer; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.StreamSink; -import com.ripple.core.types.known.sle.LedgerEntry; -import com.ripple.core.types.known.tx.result.TransactionResult; - -import java.io.*; - -public class STWriter implements BytesSink, Closeable { - BytesSink sink; - BinarySerializer serializer; - public STWriter(BytesSink bytesSink) { - serializer = new BinarySerializer(bytesSink); - sink = bytesSink; - } - - private OutputStream stream; - private STWriter(BytesSink sink, OutputStream stream) { - this(sink); - this.stream = stream; - } - - public static STWriter toFile(String path) { - try { - FileOutputStream fos = new FileOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(fos); - return new STWriter(new StreamSink(bos), bos); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } - - public void write(SerializedType obj) { - obj.toBytesSink(sink); - } - public void writeVl(SerializedType obj) { - serializer.addLengthEncoded(obj); - } - - @Override - public void add(byte aByte) { - sink.add(aByte); - } - - @Override - public void add(byte[] bytes) { - sink.add(bytes); - } - - public void write(TransactionResult result) { - write(result.hash); - writeVl(result.txn); - writeVl(result.meta); - } - - public void write(Hash256 hash256, LedgerEntry le) { - write(hash256); - writeVl(le); - } - - @Override - public void close() throws IOException { - if (this.stream != null) { - this.stream.close(); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java b/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java deleted file mode 100644 index 55552ede01..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/cache/SLECache.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.ripple.core.cache; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.types.known.sle.LedgerEntry; -import com.ripple.core.types.known.tx.result.AffectedNode; -import com.ripple.core.types.known.tx.result.TransactionMeta; -import com.ripple.core.types.known.tx.result.TransactionResult; - -import java.util.TreeMap; - -public class SLECache { - private final TreeMap cache = new TreeMap(); - - public static class CacheEntry { - public LedgerEntry le; - public UInt32 prevTxnIndex; - public UInt32 prevLedger; - public boolean deleted = false; - - public void upateLedgerEntry(LedgerEntry le, UInt32 ledgerIndex, UInt32 txnIndex) { - if (doUpdate(txnIndex, ledgerIndex)) { - // in the first case - prevTxnIndex = txnIndex; - prevLedger = ledgerIndex; - - if (le == null) { - deleted = true; - } - this.le = le; - } - } - - private boolean doUpdate(UInt32 txnIndex, UInt32 ledgerIndex) { - if (le == null && !deleted) { - return true; - } - if (prevLedger == null) { - return true; - } - int ledgerCmp = ledgerIndex.compareTo(prevLedger); - if (ledgerCmp == 1) { - return true; - } - if (ledgerCmp == 0) { - if (prevTxnIndex == null) { - // We don't know, should log a warning or something - // Should we keep the first one that we have of this index - // or can we assume that the latest is the best? - return true; - } - if (txnIndex.compareTo(prevTxnIndex) == 1) { - // This happened AFTER - return true; - } - } - //ledgerCmp == -1 or txnIndex <= previousTxnIndex ss - return false; - } - } - - public boolean cache(LedgerEntry le, UInt32 validatedLedgerIndex) { - Hash256 index = le.ledgerIndex(); - CacheEntry ce = getOrCreate(index); - ce.upateLedgerEntry(le, validatedLedgerIndex, null); - return true; - } - - private CacheEntry getEntry(Hash256 index) { - return cache.get(index); - } - - private CacheEntry createEntry(Hash256 index) { - CacheEntry ce = new CacheEntry(); - cache.put(index, ce); - return ce; - } - - public LedgerEntry get(Hash256 index) { - CacheEntry entry = getEntry(index); - return entry == null || entry.deleted ? null : entry.le; - } - - public void updateFromTransactionResult(TransactionResult tr) { - if (!tr.validated) { - return; - } - - TransactionMeta meta = tr.meta; - UInt32 ledgerIndex = tr.ledgerIndex; - UInt32 txnIndex = meta.transactionIndex(); - - for (AffectedNode an : meta.affectedNodes()) { - Hash256 index = an.ledgerIndex(); - CacheEntry ce = getOrCreate(index); - ce.upateLedgerEntry(an.isDeletedNode() ? null : (LedgerEntry) an.nodeAsFinal(), - ledgerIndex, - txnIndex); - } - } - - private CacheEntry getOrCreate(Hash256 index) { - CacheEntry already = getEntry(index); - if (already == null) { - return createEntry(index); - } else { - return already; - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java b/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java deleted file mode 100644 index 606c5b2b71..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/AccountID.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.coretypes.hash.Hash160; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.AccountIDField; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.crypto.Seed; -import com.ripple.crypto.keys.IKeyPair; -import com.ripple.encodings.addresses.Addresses; -import com.ripple.encodings.common.B16; -import com.ripple.utils.Utils; - -/** - * Originally it was intended that AccountIDs would be variable length so that's - * why they are variable length encoded as top level field objects. - * - * Note however, that in practice, all account ids are just 160 bit hashes. - * Consider the fields TakerPaysIssuer and fixed length encoding of issuers in - * amount serializations. - * - * Thus, we extend Hash160 which affords us some functionality. - */ -public class AccountID extends Hash160 { - public static final AccountID NEUTRAL = fromInteger(1); - public static final AccountID XRP_ISSUER = fromInteger(0); - - public final String address; - - public AccountID(byte[] bytes) { - this(bytes, encodeAddress(bytes)); - } - - public AccountID(byte[] bytes, String address) { - super(bytes); - this.address = address; - } - - // Static from* constructors - public static AccountID fromString(String value) { - if (value.length() == 160 / 4) { - return fromBytes(B16.decode(value)); - } else { - return fromAddress(value); - } - } - - static public AccountID fromAddress(String address) { - byte[] bytes = Addresses.decodeAccountID(address); - return new AccountID(bytes, address); - } - - static public AccountID fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - static public AccountID fromHex(String hex) { - return translate.fromHex(hex); - } - - public static AccountID fromKeyPair(IKeyPair kp) { - byte[] bytes = kp.id(); - return new AccountID(bytes, encodeAddress(bytes)); - } - - public static AccountID fromPassPhrase(String phrase) { - return fromKeyPair(Seed.fromPassPhrase(phrase).keyPair()); - } - - static public AccountID fromSeed(String seed) { - return fromKeyPair(Seed.getKeyPair(seed)); - } - - private static AccountID fromInteger(Integer n) { - return fromBytes(Utils.padTo160(new UInt32(n).toByteArray())); - } - - public static AccountID fromBytes(byte[] bytes) { - return new AccountID(bytes, encodeAddress(bytes)); - } - - @Override - public int hashCode() { - return address.hashCode(); - } - - @Override - public String toString() { - return address; - } - - public Issue issue(String code) { - return new Issue(Currency.fromString(code), this); - } - - public Issue issue(Currency c) { - return new Issue(c, this); - } - - public boolean isNativeIssuer() { - return this == XRP_ISSUER || equals(XRP_ISSUER); - } - - // SerializedType interface implementation - @Override - public Object toJSON() { - return toString(); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - to.add(bytes()); - } - - @Override - public Type type() { - return Type.AccountID; - } - - public Hash256 lineIndex(Issue issue) { - if (issue.isNative()) throw new AssertionError(); - return Index.rippleState(this, issue.issuer(), issue.currency()); - } - - public static class Translator extends TypeTranslator { - @Override - public AccountID fromParser(BinaryParser parser, Integer hint) { - if (hint == null) { - hint = 20; - } - return AccountID.fromBytes(parser.read(hint)); - } - - @Override - public String toString(AccountID obj) { - return obj.toString(); - } - - @Override - public AccountID fromString(String value) { - return AccountID.fromString(value); - } - } - - // - - static public Translator translate = new Translator(); - - // helpers - - private static String encodeAddress(byte[] address) { - return Addresses.encodeAccountID(address); - } - - // Typed field definitions - private static AccountIDField accountField(final Field f) { - return new AccountIDField() { - @Override - public Field getField() { - return f; - } - }; - } - - static public AccountIDField Account = accountField(Field.Account); - static public AccountIDField Owner = accountField(Field.Owner); - static public AccountIDField Destination = accountField(Field.Destination); - static public AccountIDField Issuer = accountField(Field.Issuer); - static public AccountIDField Target = accountField(Field.Target); - static public AccountIDField RegularKey = accountField(Field.RegularKey); - static public AccountIDField Authorize = accountField(Field.Authorize); - static public AccountIDField Unauthorize = accountField(Field.Unauthorize); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java deleted file mode 100644 index 3813a5ac09..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Amount.java +++ /dev/null @@ -1,790 +0,0 @@ -package com.ripple.core.coretypes; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.fields.AmountField; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import org.json.JSONObject; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.MathContext; -import java.math.RoundingMode; -import java.util.Objects; - -/** - * In ripple, amounts are either XRP, the native currency, or an IOU of - * a given currency as issued by a designated account. - */ -public class Amount extends Number implements SerializedType, Comparable - -{ - - private static BigDecimal TAKER_PAYS_FOR_THAT_DAMN_OFFER = new BigDecimal("1000000000000.000100"); - -// public static final Amount NEUTRAL_ZERO = new Amount(Currency.NEUTRAL, AccountID.NEUTRAL); - - /** - * Thrown when an Amount is constructed with an invalid value - */ - public static class PrecisionError extends RuntimeException { - public Amount illegal; - - public PrecisionError(String s) { - super(s); - } - - public PrecisionError(String s, Amount amount) { - super(s); - illegal = amount; - } - } - - // For rounding/multiplying/dividing - public static final MathContext MATH_CONTEXT = new MathContext(16, RoundingMode.HALF_UP); - // The maximum amount of digits in mantissa of an IOU amount - public static final int MAXIMUM_IOU_PRECISION = 16; - // The smallest quantity of an XRP is a drop, 1 millionth of an XRP - public static final int MAXIMUM_NATIVE_SCALE = 6; - // Defines bounds for native amounts - public static final BigDecimal MAX_NATIVE_VALUE = parseDecimal("100,000,000,000.0"); - public static final BigDecimal MIN_NATIVE_VALUE = parseDecimal("0.000,001"); - - // These are flags used when serializing to binary form - public static final UInt64 BINARY_FLAG_IS_IOU = new UInt64("8000000000000000", 16); - public static final UInt64 BINARY_FLAG_IS_NON_NEGATIVE_NATIVE = new UInt64("4000000000000000", 16); - - public static final Amount ONE_XRP = fromString("1.0"); - - // TODO, even though all these fields are effectively final, and only - // ever set it would be nice to actually use the final modifier. - // Perhaps create an amount builder. - - // The quantity of XRP or Issue(currency/issuer pairing) - // When native, the value unit is XRP, not drops. - private BigDecimal value; - private Currency currency; - // If the currency is XRP - private boolean isNative; - // Normally, in the constructor of an Amount the value is checked - // that it's scale/precision and quantity are correctly bounded. - // If unbounded is true, these checks are skipped. - // This is there for historical ledgers that contain amounts that - // would now be considered malformed (in the sense of the transaction - // engine result class temMALFORMED) - private boolean unbounded = false; - // The ZERO account is used for specifying the issuer for native - // amounts. In practice the issuer is never used when an - // amount is native. - private AccountID issuer; - - private UInt64 mantissa; - // The exponent is always calculated. - private int exponent; - - public Amount(BigDecimal value, Currency currency, AccountID issuer) { - this(value, currency, issuer, false); - } - - public Amount(BigDecimal xrpScaleValue) { - isNative = true; - currency = Currency.XRP; - this.setAndCheckValue(xrpScaleValue); - } - - public Amount(Number xrpScaleValue) { - isNative = true; - currency = Currency.XRP; - this.setAndCheckValue(BigDecimal.valueOf(xrpScaleValue.doubleValue())); - } - - public Amount(BigDecimal value, Currency currency, AccountID issuer, boolean isNative, boolean unbounded) { - this.isNative = isNative; - this.currency = currency; - this.unbounded = unbounded; - this.setAndCheckValue(value); - // done AFTER set value which sets some default values - this.issuer = issuer; - } - - public Amount(Currency currency, AccountID account) { - this(BigDecimal.ZERO, currency, account); - } - - // Private constructors - Amount(BigDecimal newValue, Currency currency, AccountID issuer, boolean isNative) { - this(newValue, currency, issuer, isNative, false); - } - - private Amount(BigDecimal value, String currency, String issuer) { - this(value, currency); - if (issuer != null) { - this.issuer = AccountID.fromString(issuer); - } - } - - public Amount(BigDecimal value, String currency) { - isNative = false; - this.currency = Currency.fromString(currency); - this.setAndCheckValue(value); - } - - private void setAndCheckValue(BigDecimal value) { - this.value = value.stripTrailingZeros(); - initialize(); - } - - private void initialize() { - if (isNative()) { - issuer = AccountID.XRP_ISSUER; - if (!unbounded) { - checkXRPBounds(); - } - // Offset is unused for native amounts - exponent = -6; // compared to drops. - } else { - issuer = AccountID.NEUTRAL; - exponent = calculateExponent(); - - if (value.precision() > MAXIMUM_IOU_PRECISION && !unbounded) { - String err = "value precision of " + value.precision() + - " is greater than maximum " + - "iou precision of " + MAXIMUM_IOU_PRECISION; - throw new PrecisionError(err, this); - } - } - mantissa = calculateMantissa(); - } - - private Amount newValue(BigDecimal newValue) { - return newValue(newValue, false, false); - } - - private Amount newValue(BigDecimal newValue, boolean round, boolean unbounded) { - if (round) { - newValue = roundValue(newValue, isNative); - } - return new Amount(newValue, currency, issuer, isNative, unbounded); - } - - private Amount newValue(BigDecimal val, boolean round) { - return newValue(val, round, false); - } - - /* Getters and Setters */ - - public BigDecimal value() { - return value; - } - - public Currency currency() { - return currency; - } - - public AccountID issuer() { - return issuer; - } - - public Issue issue() { - // TODO: store the currency and issuer as an Issue - return new Issue(currency, issuer); - } - - private UInt64 mantissa() { - // Having this lazily computed and then cached would give significant - // performance boosts in some single threaded contexts. Given the inputs - // for the method are at least effectively final, and the method is - // essentially a pure function, it seems probably safe to do. It - // seems at worst, that in a multi threaded context, some extra work - // will be done in rare cases? - // TODO: check this assumption - return mantissa; - } - - public int exponent() { - return exponent; - } - - public boolean isNative() { - return isNative; - } - - public String currencyString() { - return currency.toString(); - } - - public String issuerString() { - if (issuer == null) { - return ""; - } - return issuer.toString(); - } - - /* Offset & Mantissa Helpers */ - - /** - * @return a positive value for the mantissa - */ - private UInt64 calculateMantissa() { - if (isNative()) { - return new UInt64(bigIntegerDrops().abs()); - } else { - return new UInt64(bigIntegerIOUMantissa()); - } - } - - private int calculateExponent() { - return -MAXIMUM_IOU_PRECISION + value.precision() - value.scale(); - } - - private BigInteger bigIntegerIOUMantissa() { - return exactBigIntegerScaledByPowerOfTen(-exponent).abs(); - } - - private BigInteger bigIntegerDrops() { - return exactBigIntegerScaledByPowerOfTen(MAXIMUM_NATIVE_SCALE); - } - - private BigInteger exactBigIntegerScaledByPowerOfTen(int n) { - return value.scaleByPowerOfTen(n).toBigIntegerExact(); - } - - /* Equality testing */ - - private boolean equalValue(Amount amt) { - return compareTo(amt) == 0; - } - @Override - public boolean equals(Object obj) { - if (obj instanceof Amount) { - return equals((Amount) obj); - } - return super.equals(obj); - } - - public boolean equals(Amount amt) { - return equalValue(amt) && - currency.equals(amt.currency) && - (isNative() || issuer.equals(amt.issuer)); - } - - public boolean equalsExceptIssuer(Amount amt) { - return equalValue(amt) && - currencyString().equals(amt.currencyString()); - } - - public int compareTo(Amount amount) { - Objects.requireNonNull(amount); - return value.compareTo(amount.value); - } - - public boolean isZero() { - return value.signum() == 0; - } - - public boolean isNegative() { - return value.signum() == -1; - } - - // Maybe you want !isNegative() - // Any amount that !isNegative() isn't necessarily positive - // Is a zero amount strictly positive? no - public boolean isPositive() { - return value.signum() == 1; - } - - /** - - Arithmetic Operations - - There's no checking if an amount is of a different currency/issuer. - - All operations return amounts of the same currency/issuer as the - first operand. - - eg. - - amountOne.add(amountTwo) - - The currency/issuer of the resultant amount, is that of `amountOne` - - Divide and multiply are equivalent to the javascript ripple-lib - ratio_human and product_human. - - */ - public Amount add(BigDecimal augend) { - return newValue(value.add(augend), true); - } - - public Amount add(Amount augend) { - return add(augend.value); - } - - public Amount add(Number augend) { - return add(BigDecimal.valueOf(augend.doubleValue())); - } - - public Amount subtract(BigDecimal subtrahend) { - return newValue(value.subtract(subtrahend), true); - } - - public Amount subtract(Amount subtrahend) { - return subtract(subtrahend.value); - } - - public Amount subtract(Number subtrahend) { - return subtract(BigDecimal.valueOf(subtrahend.doubleValue())); - } - - public Amount multiply(BigDecimal divisor) { - return newValue(value.multiply(divisor, MATH_CONTEXT), true); - } - - public Amount multiply(Amount multiplicand) { - return multiply(multiplicand.value); - } - - public Amount multiply(Number multiplicand) { - return multiply(BigDecimal.valueOf(multiplicand.doubleValue())); - } - - public Amount divide(BigDecimal divisor) { - return newValue(value.divide(divisor, MATH_CONTEXT), true); - } - - public Amount divide(Amount divisor) { - return divide(divisor.value); - } - - public Amount divide(Number divisor) { - return divide(BigDecimal.valueOf(divisor.doubleValue())); - } - - public Amount negate() { - return newValue(value.negate()); - } - - public Amount abs() { - return newValue(value.abs()); - } - public Amount min(Amount val) { - return (compareTo(val) <= 0 ? this : val); - } - public Amount max(Amount val) { - return (compareTo(val) >= 0 ? this : val); - } - - /* Offer related helpers */ - public BigDecimal computeQuality(Amount toExchangeThisWith) { - return value.divide(toExchangeThisWith.value, MathContext.DECIMAL128); - } - /** - * @return Amount - * The real native unit is a drop, one million of which are an XRP. - * We want `one` unit at XRP scale (1e6 drops), or if it's an IOU, - * just `one`. - */ - public Amount one() { - if (isNative()) { - return ONE_XRP; - } else { - return issue().amount(1); - } - } - - /* Serialized Type implementation */ - - @Override - public Object toJSON() { - if (isNative()) { - return toDropsString(); - } else { - return toJSONObject(); - } - } - - public JSONObject toJSONObject() { - if (isNative()) { - throw new RuntimeException("Native amounts must be serialized as a string"); - } - - JSONObject out = new JSONObject(); - out.put("currency", currencyString()); - out.put("value", valueText()); - out.put("issuer", issuerString()); - return out; - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - // TODO: probably better off using long - UInt64 man = mantissa(); - - if (isNative()) { - if (!isNegative()) { - man = man.or(BINARY_FLAG_IS_NON_NEGATIVE_NATIVE); - } - to.add(man.toByteArray()); - } else { - int exponent = exponent(); - UInt64 packed; - - if (isZero()) { - packed = BINARY_FLAG_IS_IOU; - } else if (isNegative()) { - packed = man.or(new UInt64(512 + /* 0 + */ 97 + exponent).shiftLeft(64 - 10)); - } else { - packed = man.or(new UInt64(512 + 256 + 97 + exponent).shiftLeft(64 - 10)); - } - - to.add(packed.toByteArray()); - to.add(currency.bytes()); - to.add(issuer.bytes()); - } - } - - @Override - public Type type() { - return Type.Amount; - } - - public static class Translator extends TypeTranslator { - @Override - public Amount fromString(String s) { - // We need to use the full dotted.path here, otherwise - // we get confused with the AmountField Amount - return com.ripple.core.coretypes.Amount.fromString(s); - } - - @Override - public Amount fromParser(BinaryParser parser, Integer hint) { - BigDecimal value; - byte[] mantissa = parser.read(8); - byte b1 = mantissa[0], b2 = mantissa[1]; - - boolean isIOU = (b1 & 0x80) != 0; - boolean isPositive = (b1 & 0x40) != 0; - int sign = isPositive ? 1 : -1; - - if (isIOU) { - mantissa[0] = 0; - Currency curr = Currency.fromParser(parser); - AccountID issuer = AccountID.fromParser(parser); - int exponent = ((b1 & 0x3F) << 2) + ((b2 & 0xff) >> 6) - 97; - mantissa[1] &= 0x3F; - - value = new BigDecimal(new BigInteger(sign, mantissa), -exponent); - return new Amount(value, curr, issuer, false); - } else { - mantissa[0] &= 0x3F; - value = xrpFromDropsMantissa(mantissa, sign); - return new Amount(value); - } - } - - @Override - public String toString(Amount obj) { - return obj.stringRepr(); - } - - public JSONObject toJSONObject(Amount obj) { - return obj.toJSONObject(); - } - - @Override - public Amount fromJSONObject(JSONObject jsonObject) { - String valueString = jsonObject.getString("value"); - String issuerString = jsonObject.getString("issuer"); - String currencyString = jsonObject.getString("currency"); - return new Amount(new BigDecimal(valueString), currencyString, issuerString); - } - - @Override - public Amount fromJacksonObject(ObjectNode object) { - checkField(object, "value"); - checkField(object, "issuer"); - checkField(object, "currency"); - String value = object.get("value").asText(); - String issuer = object.get("issuer").asText(); - String currency = object.get("currency").asText(); - return new Amount(new BigDecimal(value), currency, issuer); - } - - private void checkField(ObjectNode object, String field) { - if (!object.has(field)) { - throw new IllegalArgumentException(object + "is missing `" + - field + "`"); - } - } - } - static public Translator translate = new Translator(); - - public static BigDecimal xrpFromDropsMantissa(byte[] mantissa, int sign) { - return new BigDecimal(new BigInteger(sign, mantissa), 6); - } - - /* Number overides */ - @Override - public int intValue() { - return value.intValueExact(); - } - - @Override - public long longValue() { - return value.longValueExact(); - } - - @Override - public float floatValue() { - return value.floatValue(); - } - - @Override - public double doubleValue() { - return value.doubleValue(); - } - - public BigInteger bigIntegerValue() { - return value.toBigIntegerExact(); - } - - public Amount newIssuer(AccountID issuer) { - return new Amount(value, currency, issuer, isNative, unbounded); - } - - public Amount copy() { - return new Amount(value, currency, issuer, isNative, unbounded); - } - - // Static constructors - public static Amount fromString(String val) { - if (val.contains("/")) { - return fromIOUString(val); - } else if (val.contains(".")) { - return fromXrpString(val); - } else { - return fromDropString(val); - } - - } - - public static Amount fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static Amount fromHex(String hex) { - return translate.fromHex(hex); - } - public static Amount fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - public static Amount fromJSONObject(JSONObject jsonObject) { - return translate.fromJSONObject(jsonObject); - } - - public static Amount fromJacksonObject(ObjectNode object) { - return translate.fromJacksonObject(object); - } - - public static Amount fromValue(Object amount) { - return translate.fromValue(amount); - } - - public static Amount fromDropString(String val) { - BigDecimal xrp = new BigDecimal(val).scaleByPowerOfTen(-6); - checkDropsValueWhole(val); - return new Amount(xrp); - } - - public static Amount fromIOUString(String val) { - String[] split = val.split("/"); - if (split.length == 1) { - throw new RuntimeException("IOU string must be in the form " + - "number/currencyString or " + - "number/currencyString/issuerString"); - } else if (split.length == 2) { - return new Amount(new BigDecimal(split[0]), split[1]); - } else { - return new Amount(new BigDecimal(split[0]), split[1], split[2]); - } - } - - @Deprecated - private static Amount fromXrpString(String valueString) { - BigDecimal val = new BigDecimal(valueString); - return new Amount(val); - } - - /** - * @return A String representation as used by ripple json format - */ - public String stringRepr() { - if (isNative()) { - return toDropsString(); - } else { - return iouTextFull(); - } - } - - public String toDropsString() { - if (!isNative()) { - throw new RuntimeException("Amount is not native"); - } - return bigIntegerDrops().toString(); - } - - private String iouText() { - return String.format("%s/%s", valueText(), currencyString()); - } - - public String iouTextFull() { - return String.format("%s/%s/%s", valueText(), currencyString(), issuerString()); - } - - public String toTextFull() { - if (isNative()) { - return nativeText(); - } else { - return iouTextFull(); - } - } - - public String nativeText() { - return String.format("%s/XRP", valueText()); - } - - @Override - public String toString() { - return toTextFull(); - } - - public String toText() { - if (isNative()) { - return nativeText(); - } else { - return iouText(); - } - } - - /** - * @return A String containing the value (in XRP scale when native) - * as a decimal number - * - */ - public String valueText() { - return value.signum() == 0 ? "0" : value().toPlainString(); - } - - private void checkLowerDropBound(BigDecimal val) { - if (val.scale() > 6) { - PrecisionError bigger = getOutOfBoundsError(val, - "smaller than min native value", - MIN_NATIVE_VALUE); - bigger.illegal = this; - throw bigger; - } - } - - private void checkUpperBound(BigDecimal val) { - if (val.compareTo(MAX_NATIVE_VALUE) > 0) { - PrecisionError bigger = getOutOfBoundsError(val, - "bigger than max native value ", - MAX_NATIVE_VALUE); - bigger.illegal = this; - throw bigger; - } - } - - private static PrecisionError getOutOfBoundsError( - BigDecimal abs, - String sized, - BigDecimal bound) { - return new PrecisionError( - abs.toPlainString() + " absolute XRP is " + sized + bound); - } - - private void checkXRPBounds() { - BigDecimal v = value.abs(); - try { - checkLowerDropBound(v); - checkUpperBound(v); - } catch (PrecisionError e) { - if (v.compareTo(TAKER_PAYS_FOR_THAT_DAMN_OFFER) == 0) { - return; - } - throw e; - } - } - - - private static int significantDigits(BigDecimal input) { - input = input.stripTrailingZeros(); - return input.scale() < 0 - ? input.precision() - input.scale() - : input.precision(); - } - - public int significantDigits() { - return significantDigits(value); - } - - public static void checkDropsValueWhole(String drops) { - boolean contains = drops.contains("."); - if (contains) { - throw new RuntimeException("Drops string contains floating point is decimal"); - } - } - - public static BigDecimal roundValue(BigDecimal value, boolean nativeSrc) { - int i = value.precision() - value.scale(); - return value.setScale(nativeSrc ? MAXIMUM_NATIVE_SCALE : - MAXIMUM_IOU_PRECISION - i, - MATH_CONTEXT.getRoundingMode()); - } - - private static BigDecimal parseDecimal(String s) { - return new BigDecimal(s.replace(",", "")); //# .scaleByPowerOfTen(6); - } - - private static AmountField amountField(final Field f) { - return new AmountField() { - @Override - public Field getField() { - return f; - } - }; - } - - static public AmountField Amount = amountField(Field.Amount); - static public AmountField Balance = amountField(Field.Balance); - static public AmountField LimitAmount = amountField(Field.LimitAmount); - static public AmountField DeliveredAmount = amountField(Field.DeliveredAmount); - static public AmountField TakerPays = amountField(Field.TakerPays); - static public AmountField TakerGets = amountField(Field.TakerGets); - static public AmountField LowLimit = amountField(Field.LowLimit); - static public AmountField HighLimit = amountField(Field.HighLimit); - static public AmountField Fee = amountField(Field.Fee); - static public AmountField SendMax = amountField(Field.SendMax); - static public AmountField DeliverMin = amountField(Field.DeliverMin); - static public AmountField MinimumOffer = amountField(Field.MinimumOffer); - static public AmountField RippleEscrow = amountField(Field.RippleEscrow); - static public AmountField taker_gets_funded = amountField(Field.taker_gets_funded); - static public AmountField taker_pays_funded = amountField(Field.taker_pays_funded); - -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java deleted file mode 100644 index 48708f78f5..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Blob.java +++ /dev/null @@ -1,119 +0,0 @@ - -package com.ripple.core.coretypes; - -import com.ripple.core.fields.BlobField; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; -import org.bouncycastle.util.encoders.Hex; - -public class Blob implements SerializedType { - public Blob(byte[] bytes) { - buffer = bytes.clone(); - } - - private final byte[] buffer; - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return buffer; - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.Blob; - } - - public static Blob fromBytes(byte[] bytes) { - return new Blob(bytes); - } - - public static Blob fromHex(String hex) { - return fromBytes(B16.decode(hex)); - } - - public static Blob fromParser(BinaryParser parser, int hint) { - return translate.fromParser(parser, hint); - } - public static Blob fromParser(BinaryParser parser) { - return translate.fromParser(parser, null); - } - - public static class Translator extends TypeTranslator { - @Override - public Blob fromParser(BinaryParser parser, Integer hint) { - if (hint == null) { - hint = parser.size() - parser.pos(); - } - return new Blob(parser.read(hint)); - } - - @Override - public Object toJSON(Blob obj) { - return toString(obj); - } - - @Override - public String toString(Blob obj) { - return B16.encode(obj.buffer); - } - - @Override - public Blob fromString(String value) { - return new Blob(Hex.decode(value)); - } - - @Override - public void toBytesSink(Blob obj, BytesSink to) { - to.add(obj.buffer.clone()); - } - } - - static public Translator translate = new Translator(); - - private static BlobField blobField(final Field f) { - return new BlobField() { - @Override - public Field getField() { - return f; - } - }; - } - - static public BlobField PublicKey = blobField(Field.PublicKey); - static public BlobField MessageKey = blobField(Field.MessageKey); - static public BlobField SigningPubKey = blobField(Field.SigningPubKey); - static public BlobField TxnSignature = blobField(Field.TxnSignature); - static public BlobField MasterSignature = blobField(Field.MasterSignature); - static public BlobField Signature = blobField(Field.Signature); - static public BlobField Domain = blobField(Field.Domain); - static public BlobField FundCode = blobField(Field.FundCode); - static public BlobField RemoveCode = blobField(Field.RemoveCode); - static public BlobField ExpireCode = blobField(Field.ExpireCode); - static public BlobField CreateCode = blobField(Field.CreateCode); - - static public BlobField MemoType = blobField(Field.MemoType); - static public BlobField MemoData = blobField(Field.MemoData); - static public BlobField MemoFormat = blobField(Field.MemoFormat); - static public BlobField Condition = blobField(Field.Condition); - static public BlobField Fulfillment = blobField(Field.Fulfillment); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java deleted file mode 100644 index 27832e335b..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Currency.java +++ /dev/null @@ -1,250 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.coretypes.hash.Hash160; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.encodings.common.B16; -import com.ripple.utils.Utils; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.MathContext; -import java.util.Date; -import java.util.concurrent.TimeUnit; - -/** - * Funnily enough, yes, in rippled a currency is represented by a Hash160 type. - * For the sake of consistency and convenience, this quirk is repeated here. - * - * https://gist.github.com/justmoon/8597643 - */ -public class Currency extends Hash160 { - public static final Currency NEUTRAL = new Currency(Utils.padTo160(BigInteger.ONE.toByteArray())); - public static final Currency XRP = new Currency(Utils.padTo160(BigInteger.ZERO.toByteArray())); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - public boolean isNative() { - return this == Currency.XRP || equals(Currency.XRP); - } - - public boolean isIOU() { - return !isNative(); - } - - public static enum Type { - HASH, - ISO, // three letter isoCode - DEMURRAGE, - UNKNOWN; - - public static Type fromByte(byte typeByte) { - if (typeByte == 0x00) { - return ISO; - } else if (typeByte == 0x01) { - return DEMURRAGE; - } else if ((typeByte & 0x80) != 0) { - return HASH; - } else { - return UNKNOWN; - } - } - } - Type type; - - public static class Demurrage { - Date interestStart; - String isoCode; - double interestRate; - - static public BigDecimal applyRate(BigDecimal amount, BigDecimal rate, TimeUnit time, long units) { - BigDecimal appliedRate = getSeconds(time, units).divide(rate, MathContext.DECIMAL64); - BigDecimal factor = BigDecimal.valueOf(Math.exp(appliedRate.doubleValue())); - return amount.multiply(factor, MathContext.DECIMAL64); - } - - static public BigDecimal calculateRate(BigDecimal rate, TimeUnit time, long units) { - BigDecimal seconds = getSeconds(time, units); - BigDecimal log = ln(rate); - return seconds.divide(log, MathContext.DECIMAL64); - } - - private static BigDecimal ln(BigDecimal bd) { - return BigDecimal.valueOf(Math.log(bd.doubleValue())); - } - - private static BigDecimal getSeconds(TimeUnit time, long units) { - return BigDecimal.valueOf(time.toSeconds(units)); - } - - public Demurrage(byte[] bytes) { - BinaryParser parser = new BinaryParser(bytes); - parser.skip(1); // The type - isoCode = isoCodeFromBytesAndOffset(parser.read(3), 0);// The isoCode - interestStart = RippleDate.fromParser(parser); - long l = UInt64.fromParser(parser).longValue(); - interestRate = Double.longBitsToDouble(l); - } - } - public Demurrage demurrage = null; - public Currency(byte[] bytes) { - super(bytes); - type = Type.fromByte(this.hash[0]); - if (type == Type.DEMURRAGE) { - demurrage = new Demurrage(bytes); - } - } - - /** - * It's better to extend HashTranslator than the Hash160.Translator directly - * That way the generics can still vibe with the @Override - */ - private static class CurrencyTranslator extends HashTranslator { - @Override - public int byteWidth() { - return 20; - } - - @Override - public Currency newInstance(byte[] b) { - return new Currency(b); - } - - @Override - public Object toJSON(Currency obj) { - return obj.toString(); - } - - @Override - public Currency fromString(String value) { - if (value.length() == 40 /* byteWidth() * 2 */) { - return newInstance(B16.decode(value)); - } else if (value.equals("XRP")) { - return XRP; - } else { - if (!(value.length() == 3)) { -// if (!value.matches("[A-Z0-9]{3}")) { - throw new RuntimeException("Currency code must be 3 characters"); - } - return newInstance(encodeCurrency(value)); - } - } - } - - public static Currency fromString(String currency) { - return translate.fromString(currency); - } - - public static Currency fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - @Override - public String toString() { - switch (type) { - case ISO: - String code = getCurrencyCodeFromTLCBytes(bytes()); - if (code.equals("XRP")) { - // HEX of the bytes - return super.toString(); - } else if (code.equals("\0\0\0")) { - return "XRP"; - } else { - // the 3 letter isoCode - return code; - } - case HASH: - case DEMURRAGE: - case UNKNOWN: - default: - return super.toString(); - } - } - - public String humanCode() { - if (type == Type.ISO) { - return getCurrencyCodeFromTLCBytes(hash); - } else if (type == Type.DEMURRAGE) { - return isoCodeFromBytesAndOffset(hash, 1); - } else { - throw new IllegalStateException("No human code for currency of type " + type); - } - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Currency) { - Currency other = (Currency) obj; - byte[] bytes = this.bytes(); - byte[] otherBytes = other.bytes(); - - if (type == Type.ISO && other.type == Type.ISO) { - return (bytes[12] == otherBytes[12] && - bytes[13] == otherBytes[13] && - bytes[14] == otherBytes[14]); - } - } - return super.equals(obj); // Full comparison - } - - private static CurrencyTranslator translate = new CurrencyTranslator(); - - /* - * The following are static methods, legacy from when there was no - * usage of Currency objects, just String with "XRP" ambiguity. - * */ - public static byte[] encodeCurrency(String currencyCode) { - byte[] currencyBytes = new byte[20]; - currencyBytes[12] = (byte) currencyCode.codePointAt(0); - currencyBytes[13] = (byte) currencyCode.codePointAt(1); - currencyBytes[14] = (byte) currencyCode.codePointAt(2); - return currencyBytes; - } - - public static String getCurrencyCodeFromTLCBytes(byte[] bytes) { - int i; - boolean zeroInNonCurrencyBytes = true; - - for (i = 0; i < 20; i++) { - zeroInNonCurrencyBytes = zeroInNonCurrencyBytes && - ((i == 12 || i == 13 || i == 14) || // currency bytes (0 or any other) - bytes[i] == 0); // non currency bytes (0) - } - - if (zeroInNonCurrencyBytes) { - return isoCodeFromBytesAndOffset(bytes, 12); - } else { - throw new IllegalStateException("Currency is invalid"); - } - } - - private static char charFrom(byte[] bytes, int i) { - return (char) bytes[i]; - } - - private static String isoCodeFromBytesAndOffset(byte[] bytes, int offset) { - char a = charFrom(bytes, offset); - char b = charFrom(bytes, offset + 1); - char c = charFrom(bytes, offset + 2); - return "" + a + b + c; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java deleted file mode 100644 index 9b0c319dcf..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Flags.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; - -import java.util.BitSet; - -// TODO -public class Flags extends BitSet implements SerializedType { - @Override - public Object toJSON() { - return null; - } - - @Override - public byte[] toBytes() { - return new byte[0]; - } - - @Override - public String toHex() { - return null; - } - - @Override - public void toBytesSink(BytesSink to) { - - } - - @Override - public Type type() { - return Type.UInt32; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java deleted file mode 100644 index 44f75dae82..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Issue.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.coretypes.hash.Hash160; -import org.json.JSONObject; - -import java.math.BigDecimal; - -/** - * Represents a currency/issuer pair - */ -public class Issue implements Comparable { - - public static final Issue XRP = fromString("XRP"); - final Currency currency; - final AccountID issuer; - - public Issue(Currency currency, AccountID issuer) { - this.currency = currency; - this.issuer = issuer; - } - - public static Issue fromString(String pair) { - String[] split = pair.split("/"); - return fromStringPair(split); - } - - private static Issue fromStringPair(String[] split) { - if (split.length == 2) { - return new Issue(Currency.fromString(split[0]), AccountID.fromString(split[1])); - } else if (split[0].equals("XRP")) { - return new Issue(Currency.XRP, AccountID.XRP_ISSUER); - } else { - throw new RuntimeException("Issue string must be XRP or $currency/$issuer"); - } - } - - /** - * See {@link com.ripple.core.fields.Field#TakerGetsCurrency} - * See {@link com.ripple.core.fields.Field#TakerGetsIssuer} - * - * TODO: better handling of Taker(Gets|Pays)(Issuer|Curency) - * maybe special subclasses of AccountID / Currency - * respectively? - */ - public static Issue from160s(Hash160 currency, Hash160 issuer) { - return new Issue(new Currency(currency.bytes()), - new AccountID(issuer.toBytes())); - } - - public Currency currency() { - return currency; - } - - public AccountID issuer() { - return issuer; - } - - @Override - public String toString() { - if (isNative()) { - return "XRP"; - } else { - return String.format("%s/%s", currency, issuer); - } - } - - public JSONObject toJSON() { - JSONObject o = new JSONObject(); - o.put("currency", currency); - if (!isNative()) { - o.put("issuer", issuer); - } - return o; - } - - public Amount amount(BigDecimal value) { - return new Amount(value, currency, issuer, isNative()); - } - - public boolean isNative() { - return this == XRP || currency.equals(Currency.XRP); - } - - public Amount amount(Number value) { - return new Amount(BigDecimal.valueOf(value.doubleValue()), currency, issuer, isNative()); - } - - @Override - public int compareTo(Issue o) { - int ret = issuer.compareTo(o.issuer); - if (ret != 0) { - return ret; - } - ret = currency.compareTo(o.currency); - return ret; - } - - public Amount roundedAmount(BigDecimal amount) { - return amount(Amount.roundValue(amount, isNative())); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java b/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java deleted file mode 100644 index 0196e67f86..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/IssuePair.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ripple.core.coretypes; - -import org.json.JSONObject; - -import java.text.MessageFormat; - -public class IssuePair implements Comparable { - public final Issue pays; - public final Issue gets; - - public IssuePair(Issue pays, Issue gets) { - this.pays = pays; - this.gets = gets; - } - - @Override - public String toString() { - return MessageFormat.format("{0}/{1}", pays, gets); - } - - @Override - public int compareTo(IssuePair o) { - int cmp = pays.compareTo(o.pays); - if (cmp == 0) { - cmp = gets.compareTo(o.gets); - } - return cmp; - } - - public JSONObject toJSON() { - JSONObject ret = new JSONObject(); - ret.put("taker_gets", gets.toJSON()); - ret.put("taker_pays", pays.toJSON()); - return ret; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java b/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java deleted file mode 100644 index b054229787..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/PathSet.java +++ /dev/null @@ -1,273 +0,0 @@ -package com.ripple.core.coretypes; - -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.PathSetField; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.ArrayList; - -public class PathSet extends ArrayList implements SerializedType { - public static byte PATH_SEPARATOR_BYTE = (byte) 0xFF; - public static byte PATHSET_END_BYTE = (byte) 0x00; - - public PathSet(){} - - public static PathSet fromJSONArray(JSONArray array) { - return translate.fromJSONArray(array); - } - - public static PathSet fromHex(String hex) { - return translate.fromHex(hex); - } - - public static class Hop { - public static byte TYPE_ACCOUNT = (byte) 0x01; - public static byte TYPE_CURRENCY = (byte) 0x10; - public static byte TYPE_ISSUER = (byte) 0x20; - public static final int TYPE_ACCOUNT_CURRENCY_ISSUER = TYPE_CURRENCY | TYPE_ACCOUNT | TYPE_ISSUER; - public static final int TYPE_ACCOUNT_CURRENCY = TYPE_CURRENCY | TYPE_ACCOUNT; - public static int VALID_TYPE_MASK = ~(TYPE_ACCOUNT | TYPE_CURRENCY | TYPE_ISSUER); - - public AccountID account; - public AccountID issuer; - public Currency currency; - private int type; - - public boolean hasIssuer() { - return issuer != null; - } - public boolean hasCurrency() { - return currency != null; - } - public boolean hasAccount() { - return account != null; - } - - public int getType() { - if (type == 0) { - synthesizeType(); - } - return type; - } - - static public Hop fromJSONObject(JSONObject json) { - Hop hop = new Hop(); - if (json.has("account")) { - hop.account = AccountID.fromAddress(json.getString("account")); - } - if (json.has("issuer")) { - hop.issuer = AccountID.fromAddress(json.getString("issuer")); - } - if (json.has("currency")) { - hop.currency = Currency.fromString(json.getString("currency")); - } - if (json.has("type")) { - hop.type = json.getInt("type"); - } - return hop; - } - - public void synthesizeType() { - type = 0; - - if (hasAccount()) type |= TYPE_ACCOUNT; - if (hasCurrency()) type |= TYPE_CURRENCY; - if (hasIssuer()) type |= TYPE_ISSUER; - } - - public JSONObject toJSONObject() { - JSONObject object = new JSONObject(); - object.put("type", getType()); - - if (hasAccount()) object.put("account", account.toJSON()); - if (hasIssuer()) object.put("issuer", issuer.toJSON()); - if (hasCurrency()) object.put("currency", currency.toJSON()); - return object; - } - - public static Hop fromJacksonObject(ObjectNode json) { - Hop hop = new Hop(); - if (json.has("account")) { - hop.account = AccountID.fromAddress(json.get("account").asText()); - } - if (json.has("issuer")) { - hop.issuer = AccountID.fromAddress(json.get("issuer").asText()); - } - if (json.has("currency")) { - hop.currency = Currency.fromString(json.get("currency").asText()); - } - if (json.has("type")) { - hop.type = json.get("type").asInt(); - } - return hop; - - } - } - public static class Path extends ArrayList { - static public Path fromJSONArray(JSONArray array) { - Path path = new Path(); - int nHops = array.length(); - for (int i = 0; i < nHops; i++) { - JSONObject hop = array.getJSONObject(i); - path.add(Hop.fromJSONObject(hop)); - } - - return path; - } - static public Path fromJacksonArray(ArrayNode array) { - Path path = new Path(); - int nHops = array.size(); - for (int i = 0; i < nHops; i++) { - ObjectNode hop = (ObjectNode) array.get(i); - path.add(Hop.fromJacksonObject(hop)); - } - return path; - } - public JSONArray toJSONArray() { - JSONArray array = new JSONArray(); - for (Hop hop : this) { - array.put(hop.toJSONObject()); - } - return array; - } - } - - public JSONArray toJSONArray() { - JSONArray array = new JSONArray(); - for (Path path : this) { - array.put(path.toJSONArray()); - } - return array; - } - - // SerializedType interface implementation - @Override - public Object toJSON() { - return toJSONArray(); - } - - @Override - public void toBytesSink(BytesSink buffer) { - int n = 0; - for (Path path : this) { - if (n++ != 0) { - buffer.add(PATH_SEPARATOR_BYTE); - } - for (Hop hop : path) { - int type = hop.getType(); - buffer.add((byte) type); - if (hop.hasAccount()) { - buffer.add(hop.account.bytes()); - } - if (hop.hasCurrency()) { - buffer.add(hop.currency.bytes()); - } - if (hop.hasIssuer()) { - buffer.add(hop.issuer.bytes()); - } - } - } - buffer.add(PATHSET_END_BYTE); - } - - @Override - public Type type() { - return Type.PathSet; - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - - public static class Translator extends TypeTranslator { - @Override - public PathSet fromParser(BinaryParser parser, Integer hint) { - PathSet pathSet = new PathSet(); - PathSet.Path path = null; - while (!parser.end()) { - byte type = parser.readOne(); - if (type == PATHSET_END_BYTE) { - break; - } - if (path == null) { - path = new PathSet.Path(); - pathSet.add(path); - } - if (type == PATH_SEPARATOR_BYTE) { - path = null; - continue; - } - - PathSet.Hop hop = new PathSet.Hop(); - path.add(hop); - if ((type & Hop.TYPE_ACCOUNT) != 0) { - hop.account = AccountID.fromParser(parser); - } - if ((type & Hop.TYPE_CURRENCY) != 0) { - hop.currency = Currency.fromParser(parser); - } - if ((type & Hop.TYPE_ISSUER) != 0) { - hop.issuer = AccountID.fromParser(parser); - } - } - - return pathSet; - } - - @Override - public PathSet fromJSONArray(JSONArray array) { - PathSet paths = new PathSet(); - - int nPaths = array.length(); - - for (int i = 0; i < nPaths; i++) { - JSONArray path = array.getJSONArray(i); - paths.add(Path.fromJSONArray(path)); - } - return paths; - - } - - @Override - public PathSet fromJacksonArray(ArrayNode array) { - PathSet paths = new PathSet(); - - int nPaths = array.size(); - - for (int i = 0; i < nPaths; i++) { - ArrayNode path = (ArrayNode) array.get(i); - paths.add(Path.fromJacksonArray(path)); - } - - return paths; - } - } - static public Translator translate = new Translator(); - - public static PathSet fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - public static PathSet fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - private static PathSetField pathsetField(final Field f) { - return new PathSetField(){ @Override public Field getField() {return f;}}; - } - static public PathSetField Paths = pathsetField(Field.Paths); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java deleted file mode 100644 index 212da6d78e..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Quality.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.coretypes.hash.Hash256; - -import java.math.BigDecimal; -import java.math.BigInteger; - -public class Quality { - /** - * Finds the quality (TakerPays/TakerGets) ratio packed into the last 64 - * bits of root DirectoryNode ledger indexes. - */ - public static BigDecimal fromBookDirectory(Hash256 bookDirectory, - boolean payIsNative, - boolean getIsNative) { - // The last 7 bytes contains the mantissa - byte[] mantissa = bookDirectory.slice(-7); - // Most significant byte has the exponent packed - int exponent = ( bookDirectory.get(-8) & 0xFF) - 100; - // Return the value in XRP scale, rather than drops, as stored. - int scale = -(payIsNative ? exponent - 6 : - getIsNative ? exponent + 6 : exponent); - BigInteger unsignedBig = new BigInteger(1, mantissa); - return new BigDecimal(unsignedBig, scale); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java b/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java deleted file mode 100644 index 71a94e1ce9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/RippleDate.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.BinaryParser; - -import java.text.SimpleDateFormat; -import java.util.*; - -//public class RippleDate extends Date implements SerializedType { -public class RippleDate extends Date { - private static final SimpleDateFormat sdf = new SimpleDateFormat(); - - public static long RIPPLE_EPOCH_SECONDS_OFFSET = 0x386D4380; - static { - sdf.setTimeZone(new SimpleTimeZone(0, "GMT")); - sdf.applyPattern("dd MMM yyyy HH:mm:ss z"); - - /** - * Magic constant tested and documented. - * - * Seconds since the unix epoch from unix time (accounting leap years etc) - * at 1/January/2000 GMT - */ - GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - cal.set(2000, Calendar.JANUARY, 1, 0, 0, 0); - long computed = cal.getTimeInMillis() / 1000; - assertEquals("01 Jan 2000 00:00:00 GMT", sdf.format(cal.getTime())); // TODO - assertEquals(RippleDate.RIPPLE_EPOCH_SECONDS_OFFSET, computed); - } - - static public String gmtString(Date date) { - return sdf.format(date); - } - - private static void assertEquals(String s, String s1) { - if (!s.equals(s1)) throw new AssertionError(String.format("%s != %s", s, s1)); - } - private static void assertEquals(long a, long b) { - if (a != b) throw new AssertionError(String.format("%s != %s", a, b)); - } - - private RippleDate() { - super(); - } - private RippleDate(long milliseconds) { - super(milliseconds); - } - - public long secondsSinceRippleEpoch() { - return ((this.getTime() / 1000) - RIPPLE_EPOCH_SECONDS_OFFSET); - } - public static RippleDate fromSecondsSinceRippleEpoch(Number seconds) { - return new RippleDate((seconds.longValue() + RIPPLE_EPOCH_SECONDS_OFFSET) * 1000); - } - public static RippleDate fromParser(BinaryParser parser) { - UInt32 uInt32 = UInt32.fromParser(parser); - return fromSecondsSinceRippleEpoch(uInt32); - } - public static RippleDate now() { - return new RippleDate(); - } - -/* @Override - public Object toJSON() { - return secondsSinceRippleEpoch(); - } - - @Override - public byte[] toBytes() { - return new UInt32(secondsSinceRippleEpoch()).toBytes(); - } - - @Override - public String toHex() { - return new UInt32(secondsSinceRippleEpoch()).toHex(); - } - - @Override - public void toBytesSink(BytesSink to) { - new UInt32(secondsSinceRippleEpoch()).toBytesSink(to); - }*/ -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java deleted file mode 100644 index 6e7b0191f3..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/STArray.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.ripple.core.coretypes; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.STArrayField; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.ArrayList; - -public class STArray extends ArrayList implements SerializedType { - - public JSONArray toJSONArray() { - JSONArray array = new JSONArray(); - - for (STObject so : this) { - array.put(so.toJSON()); - } - - return array; - } - - @Override - public Object toJSON() { - return toJSONArray(); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - for (STObject stObject : this) { - stObject.toBytesSink(to); - } - } - - @Override - public Type type() { - return Type.STArray; - } - - public static STArray fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - public static STArray fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - public static STArray fromHex(String hex) { - return translate.fromHex(hex); - } - - public static class Translator extends TypeTranslator { - @Override - public STArray fromParser(BinaryParser parser, Integer hint) { - STArray stArray = new STArray(); - while (!parser.end()) { - Field field = parser.readField(); - if (field == Field.ArrayEndMarker) { - break; - } - STObject outer = new STObject(); - // assert field.getType() == Type.STObject; - outer.put(field, STObject.fromParser(parser)); - stArray.add(STObject.formatted(outer)); - } - return stArray; - } - - public JSONArray toJSONArray(STArray obj) { - return obj.toJSONArray(); - } - - @Override - public STArray fromJSONArray(JSONArray jsonArray) { - STArray arr = new STArray(); - - for (int i = 0; i < jsonArray.length(); i++) { - Object o = jsonArray.get(i); - arr.add(STObject.fromJSONObject((JSONObject) o)); - } - - return arr; - } - @Override - public STArray fromJacksonArray(ArrayNode jsonArray) { - STArray arr = new STArray(); - - for (int i = 0; i < jsonArray.size(); i++) { - ObjectNode object = (ObjectNode) jsonArray.get(i); - arr.add(STObject.fromJacksonObject(object)); - } - - return arr; - } - } - static public Translator translate = new Translator(); - - public STArray(){} - - private static STArrayField starrayField(final Field f) { - return new STArrayField(){ @Override public Field getField() {return f;}}; - } - - static public STArrayField AffectedNodes = starrayField(Field.AffectedNodes); - static public STArrayField SignerEntries = starrayField(Field.SignerEntries); - static public STArrayField Signers = starrayField(Field.Signers); - - static public STArrayField Template = starrayField(Field.Template); - static public STArrayField Necessary = starrayField(Field.Necessary); - static public STArrayField Sufficient = starrayField(Field.Sufficient); - static public STArrayField Majorities = starrayField(Field.Majorities); - static public STArrayField Memos = starrayField(Field.Memos); - static public STArrayField ArrayEndMarker = starrayField(Field.ArrayEndMarker); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java deleted file mode 100644 index b02988c082..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/STObject.java +++ /dev/null @@ -1,489 +0,0 @@ -package com.ripple.core.coretypes; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash128; -import com.ripple.core.coretypes.hash.Hash160; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.uint.UInt16; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.fields.*; -import com.ripple.core.formats.Format; -import com.ripple.core.formats.LEFormat; -import com.ripple.core.formats.TxFormat; -import com.ripple.core.serialized.*; -import com.ripple.core.serialized.enums.EngineResult; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.serialized.enums.TransactionType; -import org.json.JSONObject; - -import java.util.EnumMap; -import java.util.Iterator; -import java.util.TreeMap; -import java.util.function.Predicate; - -public class STObject implements SerializedType, Iterable { - // Internally the fields are stored in a TreeMap - public static class FieldsMap extends TreeMap {} -// public static class FieldsMap extends HashMap {} - - protected FieldsMap fields; - public Format format; - - public STObject() { - fields = new FieldsMap(); - } - public STObject(FieldsMap fieldsMap) { - fields = fieldsMap; - } - - public static STObject fromJSON(String json) { - return fromJSONObject(new JSONObject(json)); - } - public static STObject fromJSONObject(JSONObject json) { - return translate.fromJSONObject(json); - } - public static STObject fromJacksonObject(ObjectNode object) { - return translate.fromJacksonObject(object); - } - public static STObject fromHex(String hex) { - return STObject.translate.fromHex(hex); - } - public static STObject fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - public static STObject fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - public static STObject fromParser(BinaryParser parser, Integer hint) { - return translate.fromParser(parser, hint); - } - - @Override - public Iterator iterator() { -// return fields.keySet().stream().sorted().iterator(); - return fields.keySet().iterator(); - } - - public String prettyJSON() { - return translate.toJSONObject(this).toString(2); - } - - /** - * @return a subclass of STObject using the same fields - * - * If the object has a TransactionType or LedgerEntryType - * then we can up)grade to a child class, with more specific - * helper methods, and we can use `instanceof` to great effect. - */ - public static STObject formatted(STObject source) { - return STObjectFormatter.format(source); - - } - - public Format getFormat() { - if (format == null) computeFormat(); - return format; - } - - public static class FormatException extends RuntimeException { - FormatException(String s) { - super(s); - } - } - - public void checkFormat() { - Format fmt = getFormat(); - EnumMap requirements = fmt.requirements(); - for (Field field : this) { - if (!requirements.containsKey(field)) { - throw new FormatException(fmt.name() + - " doesn't have field: " + field); - } - } - for (Field field : requirements.keySet()) { - Format.Requirement req = requirements.get(field); - if (!has(field)) { - if (req == Format.Requirement.REQUIRED) { - throw new FormatException(fmt.name() + - " requires " + field + " of type " - + field.getType()); - } - } else { - SerializedType type = get(field); - if (type.type() != field.getType()) { - if (!(field.getType() == Type.Hash160 && - type.type() == Type.AccountID)) { - throw new FormatException(type.toString() + - " is not " + field.getType()); - } - } - } - } - } - - public void setFormat(Format format) { - this.format = format; - } - - private void computeFormat() { - UInt16 tt = get(UInt16.TransactionType); - if (tt != null) { - setFormat(TxFormat.fromNumber(tt)); - } - UInt16 let = get(UInt16.LedgerEntryType); - if (let != null) { - setFormat(LEFormat.fromNumber(let)); - } - } - - public FieldsMap getFields() { - return fields; - } - - public SerializedType get(Field field) { - return fields.get(field); - } - - protected Hash256 signingHash(HashPrefix txSign) { - HalfSha512 signing = HalfSha512.prefixed256(txSign); - toBytesSink(signing, Field::isSigningField); - return signing.finish(); - } - - protected byte[] signingData(HashPrefix txSign) { - BytesList bl = new BytesList(); - bl.add(txSign.bytes()); - toBytesSink(bl, Field::isSigningField); - return bl.bytes(); - } - - protected static EngineResult engineResult(STObject obj) { - return (EngineResult) obj.get(Field.TransactionResult); - } - - static public LedgerEntryType ledgerEntryType(STObject obj) { - return (LedgerEntryType) obj.get(Field.LedgerEntryType); - } - - public static TransactionType transactionType(STObject obj) { - return (TransactionType) obj.get(Field.TransactionType); - } - - public SerializedType remove(Field f) { - return fields.remove(f); - } - - public boolean has(Field f) { - return fields.containsKey(f); - } - - public boolean has(T hf) { - return has(hf.getField()); - } - - public void put (UInt8Field f, UInt8 o) {put(f.getField(), o);} - public void put (Vector256Field f, Vector256 o) {put(f.getField(), o);} - public void put (BlobField f, Blob o) {put(f.getField(), o);} - public void put (UInt64Field f, UInt64 o) {put(f.getField(), o);} - public void put (UInt32Field f, UInt32 o) {put(f.getField(), o);} - public void put (UInt16Field f, UInt16 o) {put(f.getField(), o);} - public void put (PathSetField f, PathSet o) {put(f.getField(), o);} - public void put (STObjectField f, STObject o) {put(f.getField(), o);} - public void put (Hash256Field f, Hash256 o) {put(f.getField(), o);} - public void put (Hash160Field f, Hash160 o) {put(f.getField(), o);} - public void put (Hash128Field f, Hash128 o) {put(f.getField(), o);} - public void put (STArrayField f, STArray o) {put(f.getField(), o);} - public void put (AmountField f, Amount o) {put(f.getField(), o);} - public void put (AccountIDField f, AccountID o) {put(f.getField(), o);} - - public void putTranslated(T f, Object value) { - putTranslated(f.getField(), value); - } - - public STObject as(T f, Object value) { - putTranslated(f.getField(), value); - return this; - } - - public void put(Field f, SerializedType value) { - fields.put(f, value); - } - - public void putTranslated(Field f, Object value) { - TypeTranslator typeTranslator = Translators.forField(f); - SerializedType st; - try { - st = typeTranslator.fromValue(value); - } catch (Exception e) { - throw new RuntimeException("Couldn't put `" +value+ "` into field `" + f + "`", e); - } - fields.put(f, st); - } - - public AccountID get(AccountIDField f) { - return (AccountID) get(f.getField()); - } - - public Amount get(AmountField f) { - return (Amount) get(f.getField()); - } - - public STArray get(STArrayField f) { - return (STArray) get(f.getField()); - } - - public Hash128 get(Hash128Field f) { - return (Hash128) get(f.getField()); - } - - public Hash160 get(Hash160Field f) { - return (Hash160) get(f.getField()); - } - - public Hash256 get(Hash256Field f) { - return (Hash256) get(f.getField()); - } - - public STObject get(STObjectField f) { - return (STObject) get(f.getField()); - } - - public PathSet get(PathSetField f) { - return (PathSet) get(f.getField()); - } - - public UInt16 get(UInt16Field f) { - return (UInt16) get(f.getField()); - } - - public UInt32 get(UInt32Field f) { - return (UInt32) get(f.getField()); - } - - public UInt64 get(UInt64Field f) { - return (UInt64) get(f.getField()); - } - - public UInt8 get(UInt8Field f) { - return (UInt8) get(f.getField()); - } - - public Vector256 get(Vector256Field f) { - return (Vector256) get(f.getField()); - } - - public Blob get(BlobField f) { - return (Blob) get(f.getField()); - } - - // SerializedTypes implementation - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - public JSONObject toJSONObject() { - return translate.toJSONObject(this); - } - - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - public void toBytesSink(BytesSink to, Predicate p) { - BinarySerializer serializer = new BinarySerializer(to); - - for (Field field : this) { - if (p.test(field)) { - SerializedType value = fields.get(field); - serializer.add(field, value); - } - } - } - @Override - public void toBytesSink(BytesSink to) { - toBytesSink(to, field -> field.isSerialized()); - } - - @Override - public Type type() { - return Type.STObject; - } - - private static class Translator extends TypeTranslator { - - @Override - public STObject fromParser(BinaryParser parser, Integer hint) { - STObject so = new STObject(); - TypeTranslator tr; - SerializedType st; - Field field; - Integer sizeHint; - - // hint, is how many bytes to parse - if (hint != null) { - // end hint - hint = parser.pos() + hint; - } - - while (!parser.end(hint)) { - field = parser.readField(); - if (field == Field.ObjectEndMarker) { - break; - } - tr = Translators.forField(field); - sizeHint = field.isVLEncoded() ? parser.readVLLength() : null; - st = tr.fromParser(parser, sizeHint); - if (st == null) { - throw new IllegalStateException("Parsed " + field + " as null"); - } - so.put(field, st); - } - - return STObject.formatted(so); - } - - @Override - public Object toJSON(STObject obj) { - return toJSONObject(obj); - } - - public JSONObject toJSONObject(STObject obj) { - JSONObject json = new JSONObject(); - - for (Field f : obj) { - SerializedType obj1 = obj.get(f); - Object object = obj1.toJSON(); - json.put(f.name(), object); - } - - return json; - } - - @Override - public STObject fromJSONObject(JSONObject jsonObject) { - STObject so = new STObject(); - - Iterator keys = jsonObject.keys(); - while (keys.hasNext()) { - String key = (String) keys.next(); - Object value = jsonObject.get(key); - Field fieldKey = Field.fromString(key); - if (fieldKey == null) { - continue; - } - so.putTranslated(fieldKey, value); - } - return STObject.formatted(so); - } - - @Override - public STObject fromJacksonObject(ObjectNode object) { - STObject so = new STObject(); - - Iterator keys = object.fieldNames(); - while (keys.hasNext()) { - String key = keys.next(); - JsonNode value = object.get(key); - Field fieldKey = Field.fromString(key); - if (fieldKey == null) { - continue; - } - so.putTranslated(fieldKey, value); - } - return STObject.formatted(so); - } - } - - public int size() { - return fields.size(); - } - - static private Translator translate = new Translator(); - - private static STObjectField stobjectField(final Field f) { - return new STObjectField() {@Override public Field getField() {return f; } }; - } - - static public STObjectField TransactionMetaData = stobjectField(Field.TransactionMetaData); - static public STObjectField CreatedNode = stobjectField(Field.CreatedNode); - static public STObjectField DeletedNode = stobjectField(Field.DeletedNode); - static public STObjectField ModifiedNode = stobjectField(Field.ModifiedNode); - static public STObjectField PreviousFields = stobjectField(Field.PreviousFields); - static public STObjectField FinalFields = stobjectField(Field.FinalFields); - static public STObjectField NewFields = stobjectField(Field.NewFields); - static public STObjectField TemplateEntry = stobjectField(Field.TemplateEntry); - static public STObjectField Signer = stobjectField(Field.Signer); - static public STObjectField SignerEntry = stobjectField(Field.SignerEntry); - static public STObjectField ObjectEndMarker = stobjectField(Field.ObjectEndMarker); - static public STObjectField Memo = stobjectField(Field.Memo); - static public STObjectField Majority = stobjectField(Field.Majority); - - private static class Translators { - @SuppressWarnings("unused") - private static TypeTranslator get(Class kls) { - try { - java.lang.reflect.Field translate = kls.getDeclaredField("translate"); - translate.setAccessible(true); - return (TypeTranslator) translate.get(kls); - } catch (Exception e) { - throw new RuntimeException("for kls: " + kls.getSimpleName(), e); - } - } - - private static TypeTranslator forType(Type type) { - switch (type) { - case STObject: return STObject.translate; // get(STObject.class); - case Amount: return Amount.translate; // get(Amount.class); - case UInt16: return UInt16.translate; // get(UInt16.class); - case UInt32: return UInt32.translate; // get(UInt32.class); - case UInt64: return UInt64.translate; // get(UInt64.class); - case Hash128: return Hash128.translate; // get(Hash128.class); - case Hash256: return Hash256.translate; // get(Hash256.class); - case Blob: return Blob.translate; // get(Blob.class); - case AccountID: return AccountID.translate; // get(AccountID.class); - case STArray: return STArray.translate; // get(STArray.class); - case UInt8: return UInt8.translate; // get(UInt8.class); - case Hash160: return Hash160.translate; // get(Hash160.class); - case PathSet: return PathSet.translate; // get(PathSet.class); - case Vector256: return Vector256.translate; // get(Vector256.class); - default: throw new IllegalStateException("Unknown type"); - } - } - - private static TypeTranslator forField(Field field) { - if (field.tag == null) { - switch (field) { - case LedgerEntryType: - field.tag = LedgerEntryType.translate; //get(LedgerEntryType.class); - break; - case TransactionType: - field.tag = TransactionType.translate;// get(TransactionType.class); - break; - case TransactionResult: - field.tag = EngineResult.translate; // get(EngineResult.class); - break; - default: - field.tag = forType(field.getType()); - break; - } - } - return getCastedTag(field); - } - - @SuppressWarnings("unchecked") - private static TypeTranslator getCastedTag(Field field) { - return (TypeTranslator) field.tag; - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java b/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java deleted file mode 100644 index d17b6ae0ee..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/STObjectFormatter.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.ripple.core.coretypes; - -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.generic.Validation; -import com.ripple.core.types.known.sle.LedgerHashes; -import com.ripple.core.types.known.sle.entries.*; -import com.ripple.core.types.known.tx.result.AffectedNode; -import com.ripple.core.types.known.tx.result.TransactionMeta; -import com.ripple.core.types.known.tx.txns.*; -import com.ripple.core.types.known.tx.txns.pseudo.EnableAmendment; -import com.ripple.core.types.known.tx.txns.pseudo.SetFee; - -public class STObjectFormatter { - public static STObject format(STObject source) { - // This would need to go before the test that just checks - // for ledgerEntryType - if (AffectedNode.isAffectedNode(source)) { - return new AffectedNode(source); - } - - if (TransactionMeta.isTransactionMeta(source)) { - TransactionMeta meta = new TransactionMeta(); - meta.fields = source.fields; - return meta; - } - - LedgerEntryType ledgerEntryType = STObject.ledgerEntryType(source); - if (ledgerEntryType != null) { - return ledgerFormatted(source, ledgerEntryType); - } - - TransactionType transactionType = STObject.transactionType(source); - if (transactionType != null) { - return transactionFormatted(source, transactionType); - } - - if (Validation.isValidation(source)) { - Validation validation = new Validation(); - validation.fields = source.fields; - return validation; - } - - return source; - } - - private static STObject transactionFormatted(STObject source, TransactionType transactionType) { - STObject constructed = null; - switch (transactionType) { - case Payment: - constructed = new Payment(); - break; - case EscrowCreate: - constructed = new EscrowCreate(); - break; - case EscrowFinish: - constructed = new EscrowFinish(); - break; - case AccountSet: - constructed = new AccountSet(); - break; - case EscrowCancel: - constructed = new EscrowCancel(); - break; - case SetRegularKey: - constructed = new SetRegularKey(); - break; - case OfferCreate: - constructed = new OfferCreate(); - break; - case OfferCancel: - constructed = new OfferCancel(); - break; - case TicketCreate: - constructed = new TicketCreate(); - break; - case TicketCancel: - constructed = new TicketCancel(); - break; - case SignerListSet: - constructed = new SignerListSet(); - break; - case PaymentChannelCreate: - constructed = new PaymentChannelCreate(); - break; - case PaymentChannelFund: - constructed = new PaymentChannelFund(); - break; - case PaymentChannelClaim: - constructed = new PaymentChannelClaim(); - break; - case CheckCreate: - constructed = new CheckCreate(); - break; - case CheckCash: - constructed = new CheckCash(); - break; - case CheckCancel: - constructed = new CheckCancel(); - break; - case DepositPreauth: - constructed = new DepositPreauth(); - break; - case TrustSet: - constructed = new TrustSet(); - break; - case EnableAmendment: - constructed = new EnableAmendment(); - break; - case SetFee: - constructed = new SetFee(); - break; - } - - constructed.fields = source.fields; - return constructed; - - } - - private static STObject ledgerFormatted(STObject source, LedgerEntryType ledgerEntryType) { - STObject constructed = null; - switch (ledgerEntryType) { - case Escrow: - constructed = new Escrow(); - break; - case Offer: - constructed = new Offer(); - break; - case RippleState: - constructed = new RippleState(); - break; - case AccountRoot: - constructed = new AccountRoot(); - break; - case DirectoryNode: - if (source.has(AccountID.Owner)) { - constructed = new OwnerDirectory(); - } else { - constructed = new OfferDirectory(); - } - break; - case LedgerHashes: - constructed = new LedgerHashes(); - break; - case Amendments: - constructed = new Amendments(); - break; - case FeeSettings: - constructed = new FeeSettings(); - break; - case Ticket: - constructed = new Ticket(); - break; - case SignerList: - constructed = new SignerList(); - break; - case PayChannel: - constructed = new PayChannel(); - break; - case Check: - constructed = new Check(); - break; - case DepositPreauth: - constructed = new DepositPreauthLe(); - break; - } - constructed.fields = source.fields; - return constructed; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java b/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java deleted file mode 100644 index 8a5eef49e5..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/Vector256.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.ripple.core.coretypes; - -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.fields.Vector256Field; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; -import org.json.JSONArray; - -import java.util.ArrayList; - -public class Vector256 extends ArrayList implements SerializedType { - - @Override - public Object toJSON() { - return toJSONArray(); - } - - public JSONArray toJSONArray() { - JSONArray array = new JSONArray(); - - for (Hash256 hash256 : this) { - array.put(hash256.toString()); - } - - return array; - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - for (Hash256 hash256 : this) { - hash256.toBytesSink(to); - } - } - - @Override - public Type type() { - return Type.Vector256; - } - - /** - * This method puts the last element in the removed elements slot, and - * pops off the back, thus preserving contiguity but losing ordering. - * @param ledgerIndex the ledger entry index to remove - * - * Unused when the featureSortedDirectories amendment is applied: - * See: https://ripple.com/build/known-amendments/#sorteddirectories - */ - public boolean removeUnstable(Hash256 ledgerIndex) { - int i = indexOf(ledgerIndex); - if (i == -1) { - return false; - } - - int last = size() - 1; - Hash256 lastIndex = get(last); - set(i, lastIndex); - remove(last); - - return true; - } - - public static Vector256 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static Vector256 fromHex(String hex) { - return translate.fromHex(hex); - } - public static Vector256 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - public static class Translator extends TypeTranslator { - @Override - public Vector256 fromParser(BinaryParser parser, Integer hint) { - Vector256 vector256 = new Vector256(); - if (hint == null) { - hint = parser.size() - parser.pos(); - } - for (int i = 0; i < hint / 32; i++) { - vector256.add(Hash256.fromParser(parser)); - } - - return vector256; - } - - public JSONArray toJSONArray(Vector256 obj) { - return obj.toJSONArray(); - } - - @Override - public Vector256 fromJSONArray(JSONArray jsonArray) { - Vector256 vector = new Vector256(); - - for (int i = 0; i < jsonArray.length(); i++) { - String hex = jsonArray.getString(i); - vector.add(new Hash256(B16.decode(hex))); - } - - return vector; - } - @Override - public Vector256 fromJacksonArray(ArrayNode jsonArray) { - Vector256 vector = new Vector256(); - - for (int i = 0; i < jsonArray.size(); i++) { - String hex = jsonArray.get(i).asText(); - vector.add(new Hash256(B16.decode(hex))); - } - - return vector; - } - } - static public Translator translate = new Translator(); - - public Vector256(){} - - public static Vector256Field vector256Field(final Field f) { - return new Vector256Field(){ @Override public Field getField() {return f;}}; - } - - static public Vector256Field Indexes = vector256Field(Field.Indexes); - static public Vector256Field Hashes = vector256Field(Field.Hashes); - static public Vector256Field Amendments = vector256Field(Field.Amendments); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java deleted file mode 100644 index 560cce14a0..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/HalfSha512.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; - -import java.security.MessageDigest; - -public class HalfSha512 implements BytesSink { - private MessageDigest messageDigest; - - public HalfSha512() { - try { - messageDigest = MessageDigest.getInstance("SHA-512"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static HalfSha512 prefixed256(Prefix bytes) { - HalfSha512 halfSha512 = new HalfSha512(); - halfSha512.update(bytes); - return halfSha512; - } - - public void update(byte[] bytes) { - messageDigest.update(bytes); - } - - public void update(Hash256 hash) { - messageDigest.update(hash.bytes()); - } - - public MessageDigest digest() { - return messageDigest; - } - - public Hash256 finish() { - byte[] half = digestBytes(); - return new Hash256(half); - } - - private byte[] digestBytes() { - byte[] digest = messageDigest.digest(); - byte[] half = new byte[32]; - System.arraycopy(digest, 0, half, 0, 32); - return half; - } - - @Override - public void add(byte aByte) { - messageDigest.update(aByte); - } - - @Override - public void add(byte[] bytes) { - messageDigest.update(bytes); - } - - public void update(Prefix prefix) { - messageDigest.update(prefix.bytes()); - } - - public HalfSha512 add(SerializedType st) { - st.toBytesSink(this); - return this; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java deleted file mode 100644 index 898d1b2913..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; - -import java.math.BigInteger; -import java.util.Arrays; - -abstract public class Hash implements SerializedType, Comparable { - protected final byte[] hash; - - public Hash(byte[] bytes, int size) { - hash = checkHash(bytes, size); - } - - @Override - public String toString() { - return B16.encode(hash); - } - - @Override - public int hashCode() { - // Having this lazily computed and then cached would give significant - // performance boosts in some single threaded contexts. Given the inputs - // for the method are at least effectively final, and the method is - // essentially a pure function, it seems probably safe to do. It - // seems at worst, that in a multi threaded context, some extra work - // will be done in rare cases? - // TODO: check this assumption - return Arrays.hashCode(hash); - } - - private byte[] checkHash(byte[] bytes, int size) { - int length = bytes.length; - if (length > size) { - throwIllegalArg(length, "wide"); - } else if (length == size) { - // TODO: What costs for this ? - return bytes.clone(); - } else { - throwIllegalArg(length, "small"); - } - throw new IllegalStateException("Can not get here"); - } - - private void throwIllegalArg(int length, String wrongness) { - String simpleName = getClass().getSimpleName(); - throw new IllegalArgumentException("Hash length of " + length + "bytes is too " + - wrongness + - " for " + simpleName); - } - - BigInteger bigInteger() { - return new BigInteger(1, hash); - } - - // TODO: Is a defensive copy worthwhile? Or just be adults? Never been a - // problem in practice, though others may not know to avoid mutating the - // returned array. Pity Java doesn't have something like C++ const. - // If you did it in one place, should do it EVERY WHERE, inputs/outputs and - // on every type that stores mutable arrays internally and the perf and - // maybe memory (at least GC stress) costs could add up. - // It's a bit like polishing a tur*. - public byte[] bytes() { - return hash.clone(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Hash) { - return Arrays.equals(hash, ((Hash) obj).hash); - } - - return super.equals(obj); - } - - @Override - public int compareTo(Subclass another) { - byte[] thisBytes = bytes(); - byte[] bytes = another.bytes(); - - return compareBytes(thisBytes, bytes, 0, thisBytes.length); - } - - public int compareStartingAt(Subclass another, int start) { - byte[] thisBytes = bytes(); - byte[] bytes = another.bytes(); - - return compareBytes(thisBytes, bytes, start, thisBytes.length); - } - - private int compareBytes(byte[] thisBytes, byte[] bytes, int start, int numBytes) { - int thisLength = thisBytes.length; - if (!(bytes.length == thisLength)) { - throw new RuntimeException(); - } - - for (int i = start; i < numBytes; i++) { - int cmp = (thisBytes[i] & 0xFF) - (bytes[i] & 0xFF); - if (cmp != 0) { - return cmp < 0 ? -1 : 1; - } - } - return 0; - } - - public byte[] slice(int start) { - return slice(start, 0); - } - - public byte get(int i) { - if (i < 0) i += hash.length; - return hash[i]; - } - - private byte[] slice(int start, int end) { - if (start < 0) start += hash.length; - if (end <= 0) end += hash.length; - - int length = end - start; - byte[] slice = new byte[length]; - - System.arraycopy(hash, start, slice, 0, length); - return slice; - } - - static public abstract class HashTranslator extends TypeTranslator { - - public abstract T newInstance(byte[] b); - public abstract int byteWidth(); - - @Override - public T fromParser(BinaryParser parser, Integer hint) { - return newInstance(parser.read(byteWidth())); - } - - @Override - public Object toJSON(T obj) { - return B16.encode(obj.hash); - } - - @Override - public T fromString(String value) { - return newInstance(B16.decode(value)); - } - - @Override - public void toBytesSink(T obj, BytesSink to) { - to.add(obj.bytes()); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java deleted file mode 100644 index 112340da9f..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash128.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Hash128Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; - -public class Hash128 extends Hash { - public Hash128(byte[] bytes) { - super(bytes, 16); - } - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.Hash128; - } - - public static Hash128 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static Hash128 fromHex(String string) { - return translate.fromHex(string); - } - public static Hash128 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - public static class Translator extends HashTranslator { - @Override - public Hash128 newInstance(byte[] b) { - return new Hash128(b); - } - - @Override - public int byteWidth() { - return 16; - } - } - - public static Translator translate = new Translator(); - - private static Hash128Field hash128Field(final Field f) { - return new Hash128Field(){ @Override public Field getField() {return f;}}; - } - - static public Hash128Field EmailHash = hash128Field(Field.EmailHash); - -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java deleted file mode 100644 index 5f237c195c..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash160.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Hash160Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; - -public class Hash160 extends Hash { - public Hash160(byte[] bytes) { - super(bytes, 20); - } - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.Hash160; - } - - public static Hash160 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static Hash160 fromHex(String string) { - return translate.fromHex(string); - } - - public static Hash160 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - public static class Translator extends HashTranslator { - @Override - public Hash160 newInstance(byte[] b) { - return new Hash160(b); - } - - @Override - public int byteWidth() { - return 20; - } - - @Override - public Hash160 fromString(String value) { - if (value.startsWith("r")) { - return newInstance(AccountID.fromAddress(value).bytes()); - } - return super.fromString(value); - } - } - public static Translator translate = new Translator(); - - private static Hash160Field hash160Field(final Field f) { - return new Hash160Field(){ @Override public Field getField() {return f;}}; - } - - static public Hash160Field TakerPaysIssuer = hash160Field(Field.TakerPaysIssuer); - static public Hash160Field TakerGetsCurrency = hash160Field(Field.TakerGetsCurrency); - static public Hash160Field TakerPaysCurrency = hash160Field(Field.TakerPaysCurrency); - static public Hash160Field TakerGetsIssuer = hash160Field(Field.TakerGetsIssuer); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java deleted file mode 100644 index 678b15ef00..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Hash256.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Hash256Field; -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; - -import java.math.BigInteger; -import java.util.TreeMap; - -public class Hash256 extends Hash { - - public static final BigInteger bookBaseSize = new BigInteger("10000000000000000", 16); - - public int divergenceDepth(Hash256 other) { - return divergenceDepth(0, other); - } - public int divergenceDepth(int i, Hash256 other) { - for (; i < 64; i++) { - if (nibblet(i) != other.nibblet(i)) { - break; - } - } - return i; - } - - public static class Hash256Map extends TreeMap { - public Hash256Map(Hash256Map cache) { - super(cache); - } - public Hash256Map() { - - } - } - public static final Hash256 ZERO_256 = new Hash256(new byte[32]); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.Hash256; - } - - public boolean isZero() { - return this == Hash256.ZERO_256 || equals(Hash256.ZERO_256); - } - - public boolean isNonZero() { - return !isZero(); - } - - public static Hash256 fromHex(String s) { - return translate.fromHex(s); - } - public static Hash256 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - public static Hash256 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - public Hash256(byte[] bytes) { - super(bytes, 32); - } - - public static Hash256 signingHash(byte[] blob) { - return prefixedHalfSha512(HashPrefix.txSign, blob); - } - - public static Hash256 prefixedHalfSha512(Prefix prefix, byte[] blob) { - HalfSha512 messageDigest = HalfSha512.prefixed256(prefix); - messageDigest.update(blob); - return messageDigest.finish(); - } - - public int nibblet(int depth) { - int byte_ix = depth > 0 ? depth / 2 : 0; - int b = super.hash[byte_ix]; - if (depth % 2 == 0) { - b = (b & 0xF0) >> 4; - } else { - b = b & 0x0F; - } - return b; - } - - public static class Translator extends HashTranslator { - @Override - public Hash256 newInstance(byte[] b) { - return new Hash256(b); - } - - @Override - public int byteWidth() { - return 32; - } - } - public static Translator translate = new Translator(); - - public static Hash256Field hash256Field(final Field f) { - return new Hash256Field(){ @Override public Field getField() {return f;}}; - } - - static public Hash256Field LedgerHash = hash256Field(Field.LedgerHash); - static public Hash256Field ParentHash = hash256Field(Field.ParentHash); - static public Hash256Field TransactionHash = hash256Field(Field.TransactionHash); - static public Hash256Field AccountHash = hash256Field(Field.AccountHash); - static public Hash256Field PreviousTxnID = hash256Field(Field.PreviousTxnID); - static public Hash256Field AccountTxnID = hash256Field(Field.AccountTxnID); - static public Hash256Field LedgerIndex = hash256Field(Field.LedgerIndex); - static public Hash256Field WalletLocator = hash256Field(Field.WalletLocator); - static public Hash256Field RootIndex = hash256Field(Field.RootIndex); - static public Hash256Field BookDirectory = hash256Field(Field.BookDirectory); - static public Hash256Field InvoiceID = hash256Field(Field.InvoiceID); - static public Hash256Field Nickname = hash256Field(Field.Nickname); - static public Hash256Field Amendment = hash256Field(Field.Amendment); - static public Hash256Field TicketID = hash256Field(Field.TicketID); - static public Hash256Field Channel = hash256Field(Field.Channel); - static public Hash256Field CheckID = hash256Field(Field.CheckID); - static public Hash256Field Digest = hash256Field(Field.Digest); - static public Hash256Field ConsensusHash = hash256Field(Field.ConsensusHash); - - static public Hash256Field hash = hash256Field(Field.hash); - static public Hash256Field index = hash256Field(Field.index); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java deleted file mode 100644 index 75a5900430..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/Index.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.ripple.core.coretypes.hash; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Currency; -import com.ripple.core.coretypes.Issue; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.hash.prefixes.LedgerSpace; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; - -import java.util.Arrays; -import java.util.List; - -import static com.ripple.core.coretypes.hash.HalfSha512.prefixed256; -import static java.util.Collections.sort; - -public class Index { - private static Hash256 createBookBase(Issue pays, Issue gets) { - return prefixed256(LedgerSpace.bookDir) - .add(pays.currency()) - .add(gets.currency()) - .add(pays.issuer()) - .add(gets.issuer()) - .finish(); - } - - /** - * - * @return a copy of index, with quality overlaid in lowest 8 bytes - */ - public static Hash256 quality(Hash256 index, UInt64 quality) { - byte[] qi = new byte[32]; - System.arraycopy(index.bytes(), 0, qi, 0, 24); - if (quality != null) System.arraycopy(quality.toBytes(), 0, qi, 24, 8); - return new Hash256(qi); - } - - /** - * @return A copy of index, with the lowest 8 bytes all zeroed. - */ - private static Hash256 zeroQuality(Hash256 fullIndex) { - return quality(fullIndex, null); - } - - public static Hash256 rippleState(AccountID a1, AccountID a2, Currency currency) { - List accounts = Arrays.asList(a1, a2); - sort(accounts); - return rippleState(accounts, currency); - } - - public static Hash256 rippleState(List sortedAccounts, Currency currency) { - HalfSha512 hasher = prefixed256(LedgerSpace.ripple); - // Low then High - for (AccountID account : sortedAccounts) account.toBytesSink(hasher); - // Currency - currency.toBytesSink(hasher); - - return hasher.finish(); - } - - /** - * - * @param rootIndex The RootIndex index for the directory node - * @param nodeIndex nullable LowNode, HighNode, OwnerNode, BookNode etc - * defining a `page` number. - * - * @return A hash of rootIndex and nodeIndex when nodeIndex is non default - * else the rootIndex. This hash is used as an index for the next - * DirectoryNode page. - */ - public static Hash256 directoryNode(Hash256 rootIndex, UInt64 nodeIndex) { - if (nodeIndex == null || nodeIndex.isZero()) { - return rootIndex; - } - - return prefixed256(LedgerSpace.dirNode) - .add(rootIndex) - .add(nodeIndex) - .finish(); - } - - public static Hash256 accountRoot(AccountID accountID) { - return prefixed256(LedgerSpace.account).add(accountID).finish(); - } - - public static Hash256 paymentChannel(AccountID account, AccountID destination, UInt32 sequence) { - return prefixed256(LedgerSpace.paymentChannel) - .add(account) - .add(destination) - .add(sequence) - .finish(); - } - - public static Hash256 escrow(AccountID account, UInt32 sequence) { - return prefixed256(LedgerSpace.escrow) - .add(account) - .add(sequence) - .finish(); - } - - public static Hash256 ownerDirectory(AccountID account) { - return Hash256.prefixedHalfSha512(LedgerSpace.ownerDir, account.bytes()); - } - - public static Hash256 transactionID(byte[] blob) { - return Hash256.prefixedHalfSha512(HashPrefix.transactionID, blob); - } - - public static Hash256 bookStart(Issue pays, Issue gets) { - return zeroQuality(createBookBase(pays, gets)); - } - - public static Hash256 bookStart(Hash256 indexFromBookRange) { - return zeroQuality(indexFromBookRange); - } - - public static Hash256 bookEnd(Hash256 base) { - byte[] end = base.bigInteger().add(Hash256.bookBaseSize).toByteArray(); - if (end.length > 32) { - byte[] source = end; - end = new byte[32]; - System.arraycopy(source, source.length - 32, end, 0, 32); - } - return new Hash256(end); - } - - public static Hash256 ledgerHashes(long prev) { - return prefixed256(LedgerSpace.skipList) - .add(new UInt32(prev >> 16)) - .finish(); - } - public static Hash256 ledgerHashes() { - return prefixed256(LedgerSpace.skipList).finish(); - } - - public static Hash256 amendments() { - return prefixed256(LedgerSpace.amendment).finish(); - } - - public static Hash256 feeSettings() { - return prefixed256(LedgerSpace.fee).finish(); - } - - public static Hash256 signerList(AccountID account) { - return prefixed256(LedgerSpace.signerList) - .add(account) - .add(UInt32.ZERO) - .finish(); - } - - public static Hash256 ticket(AccountID account, UInt32 sequence) { - return prefixed256(LedgerSpace.ticket) - .add(account) - .add(sequence) - .finish(); - } - - -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java deleted file mode 100644 index f213d4eb38..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/HashPrefix.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.ripple.core.coretypes.hash.prefixes; - -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.encodings.common.B16; - -/** - * The prefix codes are part of the Ripple protocol - * and existing codes cannot be arbitrarily changed. - */ -public enum HashPrefix implements Prefix { - transactionID ('T', 'X', 'N'), - txNode ('S', 'N', 'D'), - leafNode ('M', 'L', 'N'), - innerNode ('M', 'I', 'N'), - innerNodeV2 ('I', 'N', 'R'), - ledgerMaster ('L', 'W', 'R'), - txSign ('S', 'T', 'X'), - txMultiSign ('S', 'M', 'T'), - validation ('V', 'A', 'L'), - proposal ('P', 'R', 'P'), - manifest ('M', 'A', 'N'), - paymentChannelClaim ('C', 'L', 'M'); - - private UInt32 uInt32; - private byte[] bytes; - private String chars; - - @Override - public byte[] bytes() { - return bytes; - } - - public String toHex() { - return B16.encode(bytes); - } - - HashPrefix(char... chars) { - this.chars = new String(chars); - byte[] bytes = { - (byte) chars[0], - (byte) chars[1], - (byte) chars[2], - (byte) 0, - }; - uInt32 = UInt32.fromBytes(bytes); - this.bytes = bytes; - } - - public UInt32 uInt32() { - return uInt32; - } - - public String chars() { - return chars; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java deleted file mode 100644 index 20f5d61388..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/LedgerSpace.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ripple.core.coretypes.hash.prefixes; - -import com.ripple.core.coretypes.uint.UInt16; - -public enum LedgerSpace implements Prefix { - account('a'), - dirNode('d'), - generator('g'), - - ripple('r'), - offer('o'), // Entry for an offer. - ownerDir('O'), // Directory of things owned by an account. - bookDir('B'), // Directory of order books. - contract('c'), - skipList('s'), - escrow('u'), - amendment('f'), - fee('e'), - ticket('T'), - signerList('S'), - paymentChannel('x'), - - // no longer used - nickname('n'),; - - UInt16 uInt16; - public byte[] bytes; - - @Override - public byte[] bytes() { - return bytes; - } - - LedgerSpace(char c) { - uInt16 = new UInt16((int) c); - bytes = uInt16.toByteArray(); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java b/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java deleted file mode 100644 index 7ba8b7a62a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/hash/prefixes/Prefix.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.ripple.core.coretypes.hash.prefixes; - -public interface Prefix { - byte[] bytes(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java deleted file mode 100644 index aae0dcedf3..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.ripple.core.coretypes.uint; - -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; -import com.ripple.utils.Utils; - -import java.math.BigInteger; - -abstract public class UInt extends Number implements SerializedType, Comparable { - private final BigInteger value; - - private static BigInteger[] upperBounds = new BigInteger[8]; - private static BigInteger maxUIntVal(int bits) { - return new BigInteger("2").pow(bits).subtract(BigInteger.ONE); - } - - static { - for (int i = 0; i < 8; i++) { - upperBounds[i] = maxUIntVal((i + 1) * 8 ); - } - } - - UInt(byte[] bytes) { - value = new BigInteger(1, bytes); - checkBounds(); - } - - private void checkBounds() { - BigInteger upper = upperBounds[getByteWidth() - 1]; - if (value.compareTo(upper) > 0 || value.compareTo(BigInteger.ZERO) < 0) { - throw new IllegalArgumentException("value `" + value + - "` is illegal for " + getClass().getSimpleName()); - } - } - - UInt(BigInteger bi) { - value = (bi); - checkBounds(); - } - UInt(Number s) { - value = (BigInteger.valueOf(s.longValue())); - checkBounds(); - } - UInt(String s) { - value = (new BigInteger(s)); - checkBounds(); - } - UInt(String s, int radix) { - value = (new BigInteger(s, radix)); - checkBounds(); - } - - @Override - public String toString() { - return value.toString(); - } - - public abstract int getByteWidth(); - protected abstract Subclass instanceFrom(BigInteger n); - - public Subclass add(UInt val) { - return instanceFrom(value.add(val.value)); - } - - public Subclass subtract(UInt val) { - return instanceFrom(value.subtract(val.value)); - } - - public Subclass multiply(UInt val) { - return instanceFrom(value.multiply(val.value)); - } - - public Subclass divide(UInt val) { - return instanceFrom(value.divide(val.value)); - } - - public Subclass or(UInt val) { - return instanceFrom(value.or(val.value)); - } - - public Subclass shiftLeft(int n) { - return instanceFrom(value.shiftLeft(n)); - } - - public Subclass shiftRight(int n) { - return instanceFrom(value.shiftRight(n)); - } - - public int compareTo(UInt val) { - return value.compareTo(val.value); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof UInt) { - return equals((UInt) obj); - } - else return super.equals(obj); - } - - public boolean equals(UInt x) { - return value.equals(x.value); - } - - public String toString(int radix) { - return value.toString(radix); - } - public byte[] toByteArray() { - int length = getByteWidth(); - return Utils.leadingZeroesTrimmedOrPaddedTo(length, value.toByteArray()); - } - - abstract public Object value(); - - public BigInteger bigInteger(){ - return value; - } - - @Override - public int intValue() { - return value.intValue(); - } - - @Override - public long longValue() { - return value.longValue(); - } - - @Override - public double doubleValue() { - return value.doubleValue(); - } - - @Override - public float floatValue() { - return value.floatValue(); - } - - @Override - public byte byteValue() { - return value.byteValue(); - } - - @Override - public short shortValue() { - return value.shortValue(); - } - - public boolean lte(T sequence) { - return compareTo(sequence) < 1; - } - - public boolean testBit(int f) { - // TODO, optimized ;) // move to Uint32 - return value.testBit(f); - } - - public boolean isZero() { - return value.signum() == 0; - } - - static public abstract class UINTTranslator extends TypeTranslator { - public abstract T newInstance(BigInteger i); - public abstract int byteWidth(); - - @Override - public T fromParser(BinaryParser parser, Integer hint) { - return newInstance(new BigInteger(1, parser.read(byteWidth()))); - } - - @Override - public Object toJSON(T obj) { - if (obj.getByteWidth() <= 4) { - return obj.longValue(); - } else { - return toString(obj); - } - } - - @Override - public T fromLong(long aLong) { - return newInstance(BigInteger.valueOf(aLong)); - } - - @Override - public T fromString(String value) { - int radix = byteWidth() <= 4 ? 10 : 16; - return newInstance(new BigInteger(value, radix)); - } - - @Override - public T fromInteger(int integer) { - return fromLong(integer); - } - - @Override - public String toString(T obj) { - return B16.encode(obj.toByteArray()); - } - - @Override - public void toBytesSink(T obj, BytesSink to) { - to.add(obj.toByteArray()); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java deleted file mode 100644 index 9634cf6082..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt16.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.ripple.core.coretypes.uint; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.fields.UInt16Field; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.TypeTranslator; - -import java.math.BigInteger; - -public class UInt16 extends UInt { - public final static UInt16 ZERO = new UInt16(0); - - public static TypeTranslator translate = new UINTTranslator() { - @Override - public UInt16 newInstance(BigInteger i) { - return new UInt16(i); - } - - @Override - public int byteWidth() { - return 2; - } - }; - - public UInt16(byte[] bytes) { - super(bytes); - } - - public UInt16(BigInteger value) { - super(value); - } - - public UInt16(Number s) { - super(s); - } - - public UInt16(String s) { - super(s); - } - - public UInt16(String s, int radix) { - super(s, radix); - } - - public static UInt16 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static UInt16 fromHex(String string) { - return translate.fromHex(string); - } - - public static UInt16 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - @Override - public int getByteWidth() { - return 2; - } - - @Override - protected UInt16 instanceFrom(BigInteger n) { - return new UInt16(n); - } - - @Override - public Integer value() { - return intValue(); - } - - private static UInt16Field int16Field(final Field f) { - return new UInt16Field(){ @Override public Field getField() {return f;}}; - } - - static public UInt16Field LedgerEntryType = int16Field(Field.LedgerEntryType); - static public UInt16Field TransactionType = int16Field(Field.TransactionType); - static public UInt16Field SignerWeight = int16Field(Field.SignerWeight); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.UInt16; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java deleted file mode 100644 index b831c8607c..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt32.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.ripple.core.coretypes.uint; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.fields.UInt32Field; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.TypeTranslator; - -import java.math.BigInteger; - -public class UInt32 extends UInt { - public final static UInt32 ZERO = new UInt32(0); - - public static TypeTranslator translate = new UINTTranslator() { - @Override - public UInt32 newInstance(BigInteger i) { - return new UInt32(i); - } - - @Override - public int byteWidth() { - return 4; - } - }; - - public UInt32(byte[] bytes) { - super(bytes); - } - - public UInt32(BigInteger value) { - super(value); - } - - public UInt32(Number val) { - super(val); - } - public UInt32(String s) { - super(s); - } - - public UInt32(String s, int radix) { - super(s, radix); - } - - public static UInt32 fromParser(BinaryParser binaryParser) { - return translate.fromParser(binaryParser); - } - public static UInt32 fromHex(String string) { - return translate.fromHex(string); - } - public static UInt32 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - @Override - public int getByteWidth() { - return 4; - } - - @Override - protected UInt32 instanceFrom(BigInteger n) { - return new UInt32(n); - } - - @Override - public Long value() { - return longValue(); - } - - private static UInt32Field int32Field(final Field f) { - return new UInt32Field(){ @Override public Field getField() {return f;}}; - } - - static public UInt32Field Flags = int32Field(Field.Flags); - static public UInt32Field SourceTag = int32Field(Field.SourceTag); - static public UInt32Field Sequence = int32Field(Field.Sequence); - static public UInt32Field PreviousTxnLgrSeq = int32Field(Field.PreviousTxnLgrSeq); - static public UInt32Field LedgerSequence = int32Field(Field.LedgerSequence); - static public UInt32Field CloseTime = int32Field(Field.CloseTime); - static public UInt32Field ParentCloseTime = int32Field(Field.ParentCloseTime); - static public UInt32Field SigningTime = int32Field(Field.SigningTime); - static public UInt32Field Expiration = int32Field(Field.Expiration); - static public UInt32Field TransferRate = int32Field(Field.TransferRate); - static public UInt32Field WalletSize = int32Field(Field.WalletSize); - static public UInt32Field OwnerCount = int32Field(Field.OwnerCount); - static public UInt32Field DestinationTag = int32Field(Field.DestinationTag); - static public UInt32Field HighQualityIn = int32Field(Field.HighQualityIn); - static public UInt32Field HighQualityOut = int32Field(Field.HighQualityOut); - static public UInt32Field LowQualityIn = int32Field(Field.LowQualityIn); - static public UInt32Field LowQualityOut = int32Field(Field.LowQualityOut); - static public UInt32Field QualityIn = int32Field(Field.QualityIn); - static public UInt32Field QualityOut = int32Field(Field.QualityOut); - static public UInt32Field StampEscrow = int32Field(Field.StampEscrow); - static public UInt32Field BondAmount = int32Field(Field.BondAmount); - static public UInt32Field LoadFee = int32Field(Field.LoadFee); - static public UInt32Field OfferSequence = int32Field(Field.OfferSequence); - static public UInt32Field FirstLedgerSequence = int32Field(Field.FirstLedgerSequence); - static public UInt32Field LastLedgerSequence = int32Field(Field.LastLedgerSequence); - static public UInt32Field TransactionIndex = int32Field(Field.TransactionIndex); - static public UInt32Field OperationLimit = int32Field(Field.OperationLimit); - static public UInt32Field ReferenceFeeUnits = int32Field(Field.ReferenceFeeUnits); - static public UInt32Field ReserveBase = int32Field(Field.ReserveBase); - static public UInt32Field ReserveIncrement = int32Field(Field.ReserveIncrement); - static public UInt32Field SetFlag = int32Field(Field.SetFlag); - static public UInt32Field ClearFlag = int32Field(Field.ClearFlag); - static public UInt32Field SignerQuorum = int32Field(Field.SignerQuorum); - public static UInt32Field SignerListID = int32Field(Field.SignerListID); - public static UInt32Field CancelAfter = int32Field(Field.CancelAfter); - public static UInt32Field FinishAfter = int32Field(Field.FinishAfter); - public static UInt32Field SettleDelay = int32Field(Field.SettleDelay); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.UInt32; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java deleted file mode 100644 index 3312192542..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt64.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.ripple.core.coretypes.uint; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.fields.UInt64Field; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.TypeTranslator; - -import java.math.BigInteger; - -public class UInt64 extends UInt { - public final static UInt64 ZERO = new UInt64(0); - - public static TypeTranslator translate = new UINTTranslator() { - @Override - public UInt64 newInstance(BigInteger i) { - return new UInt64(i); - } - - @Override - public int byteWidth() { - return 8; - } - }; - - public UInt64(byte[] bytes) { - super(bytes); - } - - public UInt64(BigInteger value) { - super(value); - } - - public UInt64(Number s) { - super(s); - } - - public UInt64(String s) { - super(s); - } - - public UInt64(String s, int radix) { - super(s, radix); - } - - public static UInt64 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - - public static UInt64 fromHex(String string) { - return translate.fromHex(string); - } - public static UInt64 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - @Override - public int getByteWidth() { - return 8; - } - - @Override - protected UInt64 instanceFrom(BigInteger n) { - return new UInt64(n); - } - - @Override - public BigInteger value() { - return bigInteger(); - } - - private static UInt64Field int64Field(final Field f) { - return new UInt64Field(){ @Override public Field getField() {return f;}}; - } - - static public UInt64Field IndexNext = int64Field(Field.IndexNext); - static public UInt64Field IndexPrevious = int64Field(Field.IndexPrevious); - static public UInt64Field BookNode = int64Field(Field.BookNode); - static public UInt64Field OwnerNode = int64Field(Field.OwnerNode); - static public UInt64Field BaseFee = int64Field(Field.BaseFee); - static public UInt64Field ExchangeRate = int64Field(Field.ExchangeRate); - static public UInt64Field LowNode = int64Field(Field.LowNode); - static public UInt64Field HighNode = int64Field(Field.HighNode); - public static UInt64Field DestinationNode = int64Field(Field.DestinationNode); - public static UInt64Field Cookie = int64Field(Field.Cookie); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.UInt64; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java b/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java deleted file mode 100644 index 528eaa8614..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/coretypes/uint/UInt8.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.ripple.core.coretypes.uint; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; -import com.ripple.core.fields.UInt8Field; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.TypeTranslator; - -import java.math.BigInteger; - -public class UInt8 extends UInt { - public final static UInt8 ZERO = new UInt8(0); - - public static TypeTranslator translate = new UINTTranslator() { - @Override - public UInt8 newInstance(BigInteger i) { - return new UInt8(i); - } - - @Override - public int byteWidth() { - return 1; - } - }; - - public UInt8(byte[] bytes) { - super(bytes); - } - - public UInt8(BigInteger value) { - super(value); - } - - public UInt8(Number s) { - super(s); - } - - public UInt8(String s) { - super(s); - } - - public UInt8(String s, int radix) { - super(s, radix); - } - - public static UInt8 fromParser(BinaryParser parser) { - return translate.fromParser(parser); - } - public static UInt8 fromHex(String hex) { - return translate.fromHex(hex); - } - public static UInt8 fromBytes(byte[] bytes) { - return translate.fromBytes(bytes); - } - - @Override - public int getByteWidth() { - return 1; - } - - @Override - protected UInt8 instanceFrom(BigInteger n) { - return new UInt8(n); - } - - @Override - public Short value() { - return shortValue(); - } - - private static UInt8Field int8Field(final Field f) { - return new UInt8Field() {@Override public Field getField() {return f; } }; - } - - static public UInt8Field CloseResolution = int8Field(Field.CloseResolution); - static public UInt8Field Method = int8Field(Field.Method); - static public UInt8Field TransactionResult = int8Field(Field.TransactionResult); - static public UInt8Field TickSize = int8Field(Field.TickSize); - - @Override - public Object toJSON() { - return translate.toJSON(this); - } - - @Override - public byte[] toBytes() { - return translate.toBytes(this); - } - - @Override - public String toHex() { - return translate.toHex(this); - } - - @Override - public void toBytesSink(BytesSink to) { - translate.toBytesSink(this, to); - } - - @Override - public Type type() { - return Type.UInt8; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java b/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java deleted file mode 100644 index 99f18b5309..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/enums/LedgerFlag.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ripple.core.enums; - -// Ledger Specific Flags -public class LedgerFlag { - public static int - // ltACCOUNT_ROOT - PasswordSpent = 0x00010000, // True, if password set fee is spent. - RequireDestTag = 0x00020000, // True, to require a DestinationTag for payments. - RequireAuth = 0x00040000, // True, to require a authorization to hold IOUs. - DisallowXRP = 0x00080000, // True, to disallow sending XRP. - DisableMaster = 0x00100000, // True, force regular key - NoFreeze = 0x00200000, // True, cannot freeze ripple states - GlobalFreeze = 0x00400000, // True, all assets frozen - DefaultRipple = 0x00800000, // True, all assets frozen - - // ltOFFER - Passive = 0x00010000, - Sell = 0x00020000, // True, offer was placed as a sell. - - // ltRIPPLE_STATE - LowReserve = 0x00010000, // True, if entry counts toward reserve. - HighReserve = 0x00020000, - LowAuth = 0x00040000, - HighAuth = 0x00080000, - LowNoRipple = 0x00100000, - HighNoRipple = 0x00200000, - LowFreeze = 0x00400000, // True, low side has set freeze flag - HighFreeze = 0x00800000; // True, high side has set freeze flag -} diff --git a/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java b/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java deleted file mode 100644 index adb7f9e910..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/enums/TransactionFlag.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ripple.core.enums; - -// Transaction Specific Flags -public class TransactionFlag { - public static long - FullyCanonicalSig = 0x80000000L, - Universal = FullyCanonicalSig, - UniversalMask = ~Universal, - - // AccountSet flags: - RequireDestTag = 0x00010000, - OptionalDestTag = 0x00020000, - RequireAuth = 0x00040000, - OptionalAuth = 0x00080000, - DisallowXRP = 0x00100000, - AllowXRP = 0x00200000, - AccountSetMask = ~(Universal | RequireDestTag | OptionalDestTag - | RequireAuth | OptionalAuth - | DisallowXRP | AllowXRP), - - // AccountSet SetFlag/ClearFlag values - asfRequireDest = 1, - asfRequireAuth = 2, - asfDisallowXRP = 3, - asfDisableMaster = 4, - asfAccountTxnID = 5, - asfNoFreeze = 6, - asfGlobalFreeze = 7, - - // OfferCreate flags: - Passive = 0x00010000, - ImmediateOrCancel = 0x00020000, - FillOrKill = 0x00040000, - Sell = 0x00080000, - OfferCreateMask = ~(Universal | Passive | ImmediateOrCancel | FillOrKill | Sell), - - // Payment flags: - NoRippleDirect = 0x00010000, - PartialPayment = 0x00020000, - LimitQuality = 0x00040000, - PaymentMask = ~(Universal | PartialPayment | LimitQuality | NoRippleDirect), - - // TrustSet flags: - SetAuth = 0x00010000, - SetNoRipple = 0x00020000, - ClearNoRipple = 0x00040000, - SetFreeze = 0x00100000, - ClearFreeze = 0x00200000, - TrustSetMask = ~(Universal | SetAuth | SetNoRipple | ClearNoRipple | SetFreeze | ClearFreeze); -} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java b/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java deleted file mode 100644 index f31e3df14d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/AccountIDField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class AccountIDField implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java b/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java deleted file mode 100644 index 4666ff51f9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/AmountField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class AmountField implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java b/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java deleted file mode 100644 index 2925c89611..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/BlobField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class BlobField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Field.java deleted file mode 100644 index 87871ecca0..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Field.java +++ /dev/null @@ -1,328 +0,0 @@ -package com.ripple.core.fields; - -import java.util.*; - -public enum Field { - // These are all presorted (verified in a static block below) - // They can then be used in a TreeMap, using the Enum (private) ordinal - // comparator - Generic(0, Type.Unknown), - Invalid(-1, Type.Unknown), - - LedgerEntryType(1, Type.UInt16), - TransactionType(2, Type.UInt16), - SignerWeight(3, Type.UInt16), - - Flags(2, Type.UInt32), - SourceTag(3, Type.UInt32), - Sequence(4, Type.UInt32), - PreviousTxnLgrSeq(5, Type.UInt32), - LedgerSequence(6, Type.UInt32), - CloseTime(7, Type.UInt32), - ParentCloseTime(8, Type.UInt32), - SigningTime(9, Type.UInt32), - Expiration(10, Type.UInt32), - TransferRate(11, Type.UInt32), - WalletSize(12, Type.UInt32), - OwnerCount(13, Type.UInt32), - DestinationTag(14, Type.UInt32), - - HighQualityIn(16, Type.UInt32), - HighQualityOut(17, Type.UInt32), - LowQualityIn(18, Type.UInt32), - LowQualityOut(19, Type.UInt32), - QualityIn(20, Type.UInt32), - QualityOut(21, Type.UInt32), - StampEscrow(22, Type.UInt32), - BondAmount(23, Type.UInt32), - LoadFee(24, Type.UInt32), - OfferSequence(25, Type.UInt32), - FirstLedgerSequence(26, Type.UInt32), // Deprecated: do not use - // Added new semantics in 9486fc416ca7c59b8930b734266eed4d5b714c50 - LastLedgerSequence(27, Type.UInt32), - TransactionIndex(28, Type.UInt32), - OperationLimit(29, Type.UInt32), - ReferenceFeeUnits(30, Type.UInt32), - ReserveBase(31, Type.UInt32), - ReserveIncrement(32, Type.UInt32), - SetFlag(33, Type.UInt32), - ClearFlag(34, Type.UInt32), - SignerQuorum(35, Type.UInt32), - CancelAfter(36, Type.UInt32), - FinishAfter(37, Type.UInt32), - SignerListID(38, Type.UInt32), - SettleDelay(39, Type.UInt32), - - IndexNext(1, Type.UInt64), - IndexPrevious(2, Type.UInt64), - BookNode(3, Type.UInt64), - OwnerNode(4, Type.UInt64), - BaseFee(5, Type.UInt64), - ExchangeRate(6, Type.UInt64), - LowNode(7, Type.UInt64), - HighNode(8, Type.UInt64), - DestinationNode(9, Type.UInt64), - Cookie(10, Type.UInt64), - - EmailHash(1, Type.Hash128), - - LedgerHash(1, Type.Hash256), - ParentHash(2, Type.Hash256), - TransactionHash(3, Type.Hash256), - AccountHash(4, Type.Hash256), - PreviousTxnID(5, Type.Hash256), - LedgerIndex(6, Type.Hash256), - WalletLocator(7, Type.Hash256), - RootIndex(8, Type.Hash256), - // Added in rippled commit: 9486fc416ca7c59b8930b734266eed4d5b714c50 - AccountTxnID(9, Type.Hash256), - BookDirectory(16, Type.Hash256), - InvoiceID(17, Type.Hash256), - Nickname(18, Type.Hash256), - Amendment(19, Type.Hash256), - TicketID(20, Type.Hash256), - Digest(21, Type.Hash256), - Channel(22, Type.Hash256), - ConsensusHash(23, Type.Hash256), - CheckID(24, Type.Hash256), - - hash(257, Type.Hash256), - index(258, Type.Hash256), - - Amount(1, Type.Amount), - Balance(2, Type.Amount), - LimitAmount(3, Type.Amount), - TakerPays(4, Type.Amount), - TakerGets(5, Type.Amount), - LowLimit(6, Type.Amount), - HighLimit(7, Type.Amount), - Fee(8, Type.Amount), - SendMax(9, Type.Amount), - DeliverMin(10, Type.Amount), - - MinimumOffer(16, Type.Amount), - RippleEscrow(17, Type.Amount), - // Added in rippled commit: e7f0b8eca69dd47419eee7b82c8716b3aa5a9e39 - DeliveredAmount(18, Type.Amount), - // These are auxiliary fields -// quality(257, Type.AMOUNT), - taker_gets_funded(258, Type.Amount), - taker_pays_funded(259, Type.Amount), - - PublicKey(1, Type.Blob), - MessageKey(2, Type.Blob), - SigningPubKey(3, Type.Blob), - TxnSignature(4, Type.Blob), - Signature(6, Type.Blob), - Domain(7, Type.Blob), - FundCode(8, Type.Blob), - RemoveCode(9, Type.Blob), - ExpireCode(10, Type.Blob), - CreateCode(11, Type.Blob), - MemoType(12, Type.Blob), - MemoData(13, Type.Blob), - MemoFormat(14, Type.Blob), - Fulfillment(16, Type.Blob), - Condition(17, Type.Blob), - MasterSignature(18, Type.Blob), - - Account(1, Type.AccountID), - Owner(2, Type.AccountID), - Destination(3, Type.AccountID), - Issuer(4, Type.AccountID), - Authorize(5, Type.AccountID), - Unauthorize(6, Type.AccountID), - Target(7, Type.AccountID), - RegularKey(8, Type.AccountID), - - ObjectEndMarker(1, Type.STObject), - - TransactionMetaData(2, Type.STObject), - CreatedNode(3, Type.STObject), - DeletedNode(4, Type.STObject), - ModifiedNode(5, Type.STObject), - PreviousFields(6, Type.STObject), - FinalFields(7, Type.STObject), - NewFields(8, Type.STObject), - TemplateEntry(9, Type.STObject), - Memo(10, Type.STObject), - SignerEntry(11, Type.STObject), - Signer(16, Type.STObject), - // 17 unused - Majority(18, Type.STObject), - - ArrayEndMarker(1, Type.STArray), -// SigningAccounts(2, Type.STArray), - Signers(3, Type.STArray), - SignerEntries(4, Type.STArray), - Template(5, Type.STArray), - Necessary(6, Type.STArray), - Sufficient(7, Type.STArray), - AffectedNodes(8, Type.STArray), - Memos(9, Type.STArray), - Majorities(16, Type.STArray), - - CloseResolution(1, Type.UInt8), - Method(2, Type.UInt8), - TransactionResult(3, Type.UInt8), - TickSize(16, Type.UInt8), - - TakerPaysCurrency(1, Type.Hash160), - TakerPaysIssuer(2, Type.Hash160), - TakerGetsCurrency(3, Type.Hash160), - TakerGetsIssuer(4, Type.Hash160), - - Paths(1, Type.PathSet), - - Indexes(1, Type.Vector256), - Hashes(2, Type.Vector256), - Amendments(3, Type.Vector256), - - Transaction(1, Type.Transaction), - LedgerEntry(1, Type.LedgerEntry), - Validation(1, Type.Validation); - - final int id; - - // defaults - boolean signingField = true; - boolean isSerialized = true; - boolean isVlEncoded = false; - - public static Field fromString(String key) { - Field f; - try { - f = valueOf(key); - } catch (IllegalArgumentException e) { - f = null; - } - return f; - } - - private static byte[] asBytes(Field field) { - int name = field.getId(), type = field.getType().getId(); - ArrayList header = new ArrayList<>(3); - - if (type < 16) - { - if (name < 16) // common type, common name - header.add((byte)((type << 4) | name)); - else - { - // common type, uncommon name - header.add((byte)(type << 4)); - header.add((byte)(name)); - } - } - else if (name < 16) - { - // uncommon type, common name - header.add((byte)(name)); - header.add((byte)(type)); - } - else - { - // uncommon type, uncommon name - header.add((byte)(0)); - header.add((byte)(type)); - header.add((byte)(name)); - } - - byte[] headerBytes = new byte[header.size()]; - for (int i = 0; i < header.size(); i++) { - headerBytes[i] = header.get(i); - } - - return headerBytes; - } - - public int getId() { - return id; - } - - final int code; - final Type type; - private final byte[] bytes; - public Object tag = null; - - Field(int fid, Type tid) { - id = fid; - type = tid; - code = (type.id << 16) | fid; - isSerialized = isSerialized(this); - - if (isSerialized()) { - bytes = asBytes(this); - } else { - bytes = null; - } - } - - static private Map byCode = new TreeMap<>(); - - static public Field fromCode(Integer integer) { - return byCode.get(integer); - } - - public Type getType() { - return type; - } - - public boolean isSerialized() { - return isSerialized; - } - public boolean isVLEncoded() { - return isVlEncoded; - } - public boolean isSigningField() { - return signingField; - } - private static boolean isSerialized(Field f) { - // This should screen out `hash` and `index` and the like - return ((f.type.id > 0) && (f.type.id < 256) && (f.id > 0) && (f.id < 256)); - } - - static public Comparator comparator = Comparator.comparingInt(o -> o.code); - - static { - for (Field f : Field.values()) { - byCode.put(f.code, f); - f.isSerialized = isSerialized(f); - f.signingField = f.isSerialized; - - switch (f.type) { - case Blob: - case AccountID: - case Vector256: - f.isVlEncoded = true; - break; - default: - break; - } - - } - - TxnSignature.signingField = false; - Signers.signingField = false; - Signature.signingField = false; - MasterSignature.signingField = false; - - ArrayList sortedFields; - Field[] values = Field.values(); - sortedFields = new ArrayList<>(Arrays.asList(values)); - sortedFields.sort(comparator); - - for (int i = 0; i < values.length; i++) { - Field av = values[i]; - Field lv = sortedFields.get(i); - if (av.code != lv.code) { - throw new AssertionError( - "Field enum declaration isn't presorted"); - } - } - } - - public byte[] getBytes() { - return bytes; - } -} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/fields/HasField.java b/ripple-core/src/main/java/com/ripple/core/fields/HasField.java deleted file mode 100644 index edc49029a3..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/HasField.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.ripple.core.fields; - -public interface HasField { - Field getField(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java deleted file mode 100644 index b8b78e912e..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Hash128Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class Hash128Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java deleted file mode 100644 index f0569b13eb..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Hash160Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class Hash160Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java deleted file mode 100644 index e0a83b67ef..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Hash256Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class Hash256Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java b/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java deleted file mode 100644 index 5982570eb6..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/PathSetField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class PathSetField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java b/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java deleted file mode 100644 index 056a55c861..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/STArrayField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class STArrayField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java b/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java deleted file mode 100644 index c802f57a2a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/STObjectField.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class STObjectField implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Type.java b/ripple-core/src/main/java/com/ripple/core/fields/Type.java deleted file mode 100644 index 2384861e88..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Type.java +++ /dev/null @@ -1,35 +0,0 @@ -/* DO NOT EDIT, AUTO GENERATED */ -package com.ripple.core.fields; - -public enum Type { - Unknown(-2), - Done(-1), - NotPresent(0), - UInt16(1), - UInt32(2), - UInt64(3), - Hash128(4), - Hash256(5), - Amount(6), - Blob(7), - AccountID(8), - STObject(14), - STArray(15), - UInt8(16), - Hash160(17), - PathSet(18), - Vector256(19), - Transaction(10001), - LedgerEntry(10002), - Validation(10003); - - final int id; - - Type(int type) { - this.id = type; - } - - public int getId() { - return id; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java deleted file mode 100644 index fa99de6499..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/UInt16Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class UInt16Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java deleted file mode 100644 index a2b58902c2..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/UInt32Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class UInt32Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java deleted file mode 100644 index 3c85f3b312..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/UInt64Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class UInt64Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java b/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java deleted file mode 100644 index 465a1ad6be..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/UInt8Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class UInt8Field implements HasField {} diff --git a/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java b/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java deleted file mode 100644 index 7cadc88ea8..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/fields/Vector256Field.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.fields; - -public abstract class Vector256Field implements HasField{} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/Format.java b/ripple-core/src/main/java/com/ripple/core/formats/Format.java deleted file mode 100644 index 0061213330..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/formats/Format.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ripple.core.formats; - -import com.ripple.core.fields.Field; - -import java.util.EnumMap; - -abstract public class Format { - protected Format() { - } - - protected void addCommonFields(){} - - EnumMap requirementEnumMap = new EnumMap<>(Field.class); - EnumMap common = new EnumMap<>(Field.class); - - public EnumMap requirements() { - return requirementEnumMap; - } - - abstract public String name (); - - public Format(Object[] args) { - if ((!(args.length % 2 == 0)) || args.length < 2) { - throw new IllegalArgumentException("Varargs length should be a minimum multiple of 2"); - } - for (int i = 0; i < args.length; i+= 2) { - Field f = (Field) args[i]; - Requirement r = (Requirement) args[i + 1]; - put(f, r); - } - } - - protected void put(Field f, Requirement r) { - requirementEnumMap.put(f, r); - } - - @SuppressWarnings("unchecked") - Subclass required(Field f) { - put(f, Requirement.REQUIRED); - return (Subclass) this; - } - - @SuppressWarnings("unchecked") - Subclass optional(Field f) { - put(f, Requirement.OPTIONAL); - return (Subclass) this; - } - - @SuppressWarnings("unchecked") - Subclass nonDefault(Field f) { - put(f, Requirement.DEFAULT); - return (Subclass) this; - } - - public boolean isCommon(Field field) { - return common.containsKey(field); - } - - public static enum Requirement { - INVALID(-1), - REQUIRED( 0), - OPTIONAL( 1), - DEFAULT( 2); - Requirement(int i) {} - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java b/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java deleted file mode 100644 index 2dbd576593..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/formats/LEFormat.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.ripple.core.formats; - -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; - -import java.util.EnumMap; - -public class LEFormat extends Format { - static public EnumMap formats = new EnumMap(LedgerEntryType.class); - { - common.put(Field.LedgerIndex, Requirement.OPTIONAL); - common.put(Field.LedgerEntryType, Requirement.REQUIRED); - common.put(Field.Flags, Requirement.REQUIRED); - } - - static public LEFormat fromString(String name) { - return getLedgerFormat(LedgerEntryType.valueOf(name)); - } - - static public LEFormat fromNumber(Number ord) { - return getLedgerFormat(LedgerEntryType.fromNumber(ord)); - } - - static public LEFormat fromValue(Object o) { - if (o instanceof Number) { - return fromNumber(((Number) o).intValue()); - } else if (o instanceof String){ - return fromString((String) o); - } - else { - return null; - } - } - - public static LEFormat getLedgerFormat(LedgerEntryType key) { - if (key == null) return null; - return formats.get(key); - } - - public final LedgerEntryType ledgerEntryType; - - public LEFormat(LedgerEntryType type, Object... args) { - super(args); - ledgerEntryType = type; - addCommonFields(); - formats.put(type, this); - } - - public LEFormat(LedgerEntryType type) { - super(); - ledgerEntryType = type; - addCommonFields(); - formats.put(type, this); - } - - @Override - protected void addCommonFields() { - requirementEnumMap.putAll(common); - } - - @Override - public String name() { - return ledgerEntryType.toString(); - } - - public static LEFormat AccountRoot = new LEFormat( - LedgerEntryType.AccountRoot, - Field.Account, Requirement.REQUIRED, - Field.Sequence, Requirement.REQUIRED, - Field.Balance, Requirement.REQUIRED, - Field.OwnerCount, Requirement.REQUIRED, - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED, - Field.AccountTxnID, Requirement.OPTIONAL, - Field.RegularKey, Requirement.OPTIONAL, - Field.EmailHash, Requirement.OPTIONAL, - Field.WalletLocator, Requirement.OPTIONAL, - Field.WalletSize, Requirement.OPTIONAL, - Field.MessageKey, Requirement.OPTIONAL, - Field.TransferRate, Requirement.OPTIONAL, - Field.Domain, Requirement.OPTIONAL, - Field.TickSize, Requirement.OPTIONAL - ); - - public static LEFormat DirectoryNode = new LEFormat( - LedgerEntryType.DirectoryNode, - Field.Owner, Requirement.OPTIONAL, // for owner directories - Field.TakerPaysCurrency, Requirement.OPTIONAL, // for order book directories - Field.TakerPaysIssuer, Requirement.OPTIONAL, // for order book directories - Field.TakerGetsCurrency, Requirement.OPTIONAL, // for order book directories - Field.TakerGetsIssuer, Requirement.OPTIONAL, // for order book directories - Field.ExchangeRate, Requirement.OPTIONAL, // for order book directories - Field.Indexes, Requirement.REQUIRED, - Field.RootIndex, Requirement.REQUIRED, - Field.IndexNext, Requirement.OPTIONAL, - Field.IndexPrevious, Requirement.OPTIONAL - ); - - - public static LEFormat Offer = new LEFormat( - LedgerEntryType.Offer, - Field.Account, Requirement.REQUIRED, - Field.Sequence, Requirement.REQUIRED, - Field.TakerPays, Requirement.REQUIRED, - Field.TakerGets, Requirement.REQUIRED, - Field.BookDirectory, Requirement.REQUIRED, - Field.BookNode, Requirement.REQUIRED, - Field.OwnerNode, Requirement.REQUIRED, - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED, - Field.Expiration, Requirement.OPTIONAL - ); - - public static LEFormat Ticket = new LEFormat( - LedgerEntryType.Ticket, - Field.Account, Requirement.REQUIRED, - Field.Sequence, Requirement.REQUIRED, - Field.OwnerNode, Requirement.REQUIRED, - Field.Target, Requirement.OPTIONAL, - Field.Expiration, Requirement.OPTIONAL - ); - - public static LEFormat RippleState = new LEFormat( - LedgerEntryType.RippleState, - Field.Balance, Requirement.REQUIRED, - Field.LowLimit, Requirement.REQUIRED, - Field.HighLimit, Requirement.REQUIRED, - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED, - Field.LowNode, Requirement.OPTIONAL, - Field.LowQualityIn, Requirement.OPTIONAL, - Field.LowQualityOut, Requirement.OPTIONAL, - Field.HighNode, Requirement.OPTIONAL, - Field.HighQualityIn, Requirement.OPTIONAL, - Field.HighQualityOut, Requirement.OPTIONAL - ); - - public static LEFormat Escrow = new LEFormat( - LedgerEntryType.Escrow, - Field.Account, Requirement.REQUIRED, - Field.Destination, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED, - Field.OwnerNode, Requirement.REQUIRED, - - Field.Condition, Requirement.OPTIONAL, - Field.CancelAfter, Requirement.OPTIONAL, - Field.FinishAfter, Requirement.OPTIONAL, - Field.SourceTag, Requirement.OPTIONAL, - Field.DestinationTag, Requirement.OPTIONAL, - Field.DestinationNode, Requirement.OPTIONAL - ); - - public static LEFormat LedgerHashes = new LEFormat( - LedgerEntryType.LedgerHashes, - Field.FirstLedgerSequence, Requirement.OPTIONAL, // Remove if we do a ledger restart - Field.LastLedgerSequence, Requirement.OPTIONAL, - Field.Hashes, Requirement.REQUIRED - ); - - public static LEFormat Amendments = new LEFormat( - LedgerEntryType.Amendments, - Field.Amendments, Requirement.OPTIONAL, - Field.Majorities, Requirement.OPTIONAL - ); - - public static LEFormat SignerList = new LEFormat( - LedgerEntryType.SignerList, - - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED, - Field.OwnerNode, Requirement.REQUIRED, - - Field.SignerQuorum, Requirement.REQUIRED, - Field.SignerEntries, Requirement.REQUIRED, - Field.SignerListID, Requirement.REQUIRED - ); - - public static LEFormat FeeSettings = new LEFormat( - LedgerEntryType.FeeSettings, - Field.BaseFee, Requirement.REQUIRED, - Field.ReferenceFeeUnits, Requirement.REQUIRED, - Field.ReserveBase, Requirement.REQUIRED, - Field.ReserveIncrement, Requirement.REQUIRED - ); - - public static LEFormat PayChannel = new LEFormat( - LedgerEntryType.PayChannel, - Field.Account, Requirement.REQUIRED, - Field.Destination, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - Field.Balance, Requirement.REQUIRED, - Field.PublicKey, Requirement.REQUIRED, - Field.SettleDelay, Requirement.REQUIRED, - Field.Expiration, Requirement.OPTIONAL, - Field.CancelAfter, Requirement.OPTIONAL, - Field.SourceTag, Requirement.OPTIONAL, - Field.DestinationTag, Requirement.OPTIONAL, - Field.OwnerNode, Requirement.REQUIRED, - Field.PreviousTxnID, Requirement.REQUIRED, - Field.PreviousTxnLgrSeq, Requirement.REQUIRED - ); - - public static LEFormat Check = new LEFormat(LedgerEntryType.Check) - .required(Field.PreviousTxnID) - .required(Field.PreviousTxnLgrSeq) - .required(Field.Account) - .required(Field.Destination) - .required(Field.SendMax) - .required(Field.Sequence) - .required(Field.OwnerNode) - .required(Field.DestinationNode) - .optional(Field.Expiration) - .optional(Field.InvoiceID) - .optional(Field.SourceTag) - .optional(Field.DestinationTag) - - ; - - public static LEFormat DepositPreauth = new LEFormat(LedgerEntryType.DepositPreauth) - .required(Field.Account) - .required(Field.Authorize) - .required(Field.OwnerNode) - .required(Field.PreviousTxnID) - .required(Field.PreviousTxnLgrSeq) - ; - -} diff --git a/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java b/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java deleted file mode 100644 index fa66d27533..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/formats/TxFormat.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.ripple.core.formats; - -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.TransactionType; - -import java.util.EnumMap; - -public class TxFormat extends Format { - static public EnumMap formats = new EnumMap<>(TransactionType.class); - { - common.put(Field.TransactionType, Requirement.REQUIRED); - common.put(Field.Account, Requirement.REQUIRED); - common.put(Field.Sequence, Requirement.REQUIRED); - common.put(Field.Fee, Requirement.REQUIRED); - common.put(Field.SigningPubKey, Requirement.REQUIRED); - - common.put(Field.Flags, Requirement.OPTIONAL); - common.put(Field.SourceTag, Requirement.OPTIONAL); - common.put(Field.PreviousTxnID, Requirement.OPTIONAL); - common.put(Field.OperationLimit, Requirement.OPTIONAL); - common.put(Field.TxnSignature, Requirement.OPTIONAL); - common.put(Field.AccountTxnID, Requirement.OPTIONAL); - common.put(Field.LastLedgerSequence, Requirement.OPTIONAL); - common.put(Field.Memos, Requirement.OPTIONAL); - common.put(Field.Signers, Requirement.OPTIONAL); - - } - public final TransactionType transactionType; - - static public TxFormat fromString(String name) { - return getTxFormat(TransactionType.valueOf(name)); - } - - static public TxFormat fromNumber(Number ord) { - return getTxFormat(TransactionType.fromNumber(ord)); - } - - private static TxFormat getTxFormat(TransactionType key) { - if (key == null) return null; - return formats.get(key); - } - - public TxFormat(TransactionType type, Object... args) { - super(args); - transactionType = type; - addCommonFields(); - formats.put(transactionType, this); - } - - public TxFormat(TransactionType type) { - super(); - transactionType = type; - addCommonFields(); - formats.put(transactionType, this); - } - - @Override - protected void addCommonFields() { - requirementEnumMap.putAll(common); - } - - @Override - public String name() { - return transactionType.toString(); - } - - private static TxFormat makeFormat(TransactionType tt) { - return new TxFormat(tt); - } - - static public TxFormat AccountSet = makeFormat( - TransactionType.AccountSet) - .optional(Field.EmailHash) - .optional(Field.EmailHash) - .optional(Field.WalletLocator) - .optional(Field.WalletSize) - .optional(Field.MessageKey) - .optional(Field.Domain) - .optional(Field.TransferRate) - .optional(Field.SetFlag) - .optional(Field.TickSize) - .optional(Field.ClearFlag); - - static public TxFormat TrustSet = new TxFormat( - TransactionType.TrustSet, - Field.LimitAmount, Requirement.OPTIONAL, - Field.QualityIn, Requirement.OPTIONAL, - Field.QualityOut, Requirement.OPTIONAL); - - static public TxFormat OfferCreate = new TxFormat( - TransactionType.OfferCreate, - Field.TakerPays, Requirement.REQUIRED, - Field.TakerGets, Requirement.REQUIRED, - Field.Expiration, Requirement.OPTIONAL, - Field.OfferSequence, Requirement.OPTIONAL); - - static public TxFormat OfferCancel = new TxFormat( - TransactionType.OfferCancel, - Field.OfferSequence, Requirement.REQUIRED); - - static public TxFormat TicketCreate = new TxFormat( - TransactionType.TicketCreate, - Field.Target, Requirement.OPTIONAL, - Field.Expiration, Requirement.OPTIONAL); - - static public TxFormat TicketCancel = new TxFormat( - TransactionType.TicketCancel, - Field.TicketID, Requirement.REQUIRED); - - static public TxFormat SetRegularKey = new TxFormat( - TransactionType.SetRegularKey, - Field.RegularKey, Requirement.OPTIONAL); - - static public TxFormat Payment = new TxFormat( - TransactionType.Payment, - Field.Destination, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - Field.SendMax, Requirement.OPTIONAL, - Field.Paths, Requirement.DEFAULT, - Field.InvoiceID, Requirement.OPTIONAL, - Field.DestinationTag, Requirement.OPTIONAL, - Field.DeliverMin, Requirement.OPTIONAL - ); - - - static public TxFormat EscrowCreate = new TxFormat( - TransactionType.EscrowCreate, - Field.Destination, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - Field.Condition, Requirement.OPTIONAL, - Field.CancelAfter, Requirement.OPTIONAL, - Field.FinishAfter, Requirement.OPTIONAL, - Field.DestinationTag, Requirement.OPTIONAL); - - static public TxFormat EscrowFinish = new TxFormat( - TransactionType.EscrowFinish, - Field.Owner, Requirement.REQUIRED, - Field.OfferSequence, Requirement.REQUIRED, - Field.Fulfillment, Requirement.OPTIONAL, - Field.Condition, Requirement.OPTIONAL); - - static public TxFormat EscrowCancel = new TxFormat( - TransactionType.EscrowCancel, - Field.Owner, Requirement.REQUIRED, - Field.OfferSequence, Requirement.REQUIRED); - - static public TxFormat EnableAmendment = new TxFormat( - TransactionType.EnableAmendment, - Field.LedgerSequence, Requirement.REQUIRED, - Field.Amendment, Requirement.REQUIRED); - - static public TxFormat SetFee = new TxFormat( - TransactionType.SetFee, - Field.BaseFee, Requirement.REQUIRED, - Field.ReferenceFeeUnits, Requirement.REQUIRED, - Field.ReserveBase, Requirement.REQUIRED, - Field.LedgerSequence, Requirement.OPTIONAL, - Field.ReserveIncrement, Requirement.REQUIRED - ); - - static public TxFormat SignerListSet = new TxFormat( - TransactionType.SignerListSet, - Field.SignerQuorum, Requirement.REQUIRED, - Field.SignerEntries, Requirement.OPTIONAL - ); - static public TxFormat PaymentChannelCreate = new TxFormat( - TransactionType.PaymentChannelCreate, - Field.Destination, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - Field.SettleDelay, Requirement.REQUIRED, - Field.PublicKey, Requirement.REQUIRED, - Field.CancelAfter, Requirement.OPTIONAL, - Field.DestinationTag, Requirement.OPTIONAL - ); - static public TxFormat PaymentChannelFund = new TxFormat( - TransactionType.PaymentChannelFund, - Field.Channel, Requirement.REQUIRED, - Field.Amount, Requirement.REQUIRED, - Field.Expiration, Requirement.OPTIONAL - ); - static public TxFormat PaymentChannelClaim = new TxFormat( - TransactionType.PaymentChannelClaim, - Field.Channel, Requirement.REQUIRED, - Field.Amount, Requirement.OPTIONAL, - Field.Balance, Requirement.OPTIONAL, - Field.Signature, Requirement.OPTIONAL, - Field.PublicKey, Requirement.OPTIONAL - ); - - static public TxFormat CheckCreate = new TxFormat(TransactionType.CheckCreate) - .required(Field.Destination) - .required(Field.SendMax) - .optional(Field.Expiration) - .optional(Field.DestinationTag) - .optional(Field.InvoiceID) - ; - - static public TxFormat CheckCash = new TxFormat(TransactionType.CheckCash) - .required(Field.CheckID) - .optional(Field.Amount) - .optional(Field.DeliverMin) - ; - - static public TxFormat CheckCancel = new TxFormat(TransactionType.CheckCancel) - .required(Field.CheckID) - ; - - static public TxFormat DepositPreauth = new TxFormat(TransactionType.DepositPreauth) - .optional(Field.Authorize) - .optional(Field.Unauthorize) - ; -} diff --git a/ripple-core/src/main/java/com/ripple/core/runtime/Value.java b/ripple-core/src/main/java/com/ripple/core/runtime/Value.java deleted file mode 100644 index 1f69e88c55..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/runtime/Value.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.ripple.core.runtime; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeType; -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.List; -import java.util.Map; - -public enum Value { - UNKNOWN, - STRING, - JSON_OBJECT, - JSON_ARRAY, - - JACKSON_ARRAY, - JACKSON_BINARY, - JACKSON_BOOLEAN, - JACKSON_MISSING, - JACKSON_NULL, - JACKSON_NUMBER, - JACKSON_OBJECT, - JACKSON_POJO, - JACKSON_STRING, - - LIST, - MAP, - NUMBER, - BYTE, - DOUBLE, - FLOAT, - INTEGER, - LONG, - BYTE_ARRAY, - SHORT, - BOOLEAN; - - static public Value typeOf (Object object) { - if (object instanceof String) { - return STRING; - } - else if (object instanceof Number) { - if (object instanceof Byte) { - return BYTE; - } - else if (object instanceof Double) { - return DOUBLE; - } - else if (object instanceof Float) { - return FLOAT; - } - else if (object instanceof Integer) { - return INTEGER; - } - else if (object instanceof Long) { - return LONG; - } - else if (object instanceof Short) { - return SHORT; - } - return NUMBER; - } - else if (object instanceof JSONObject) { - return JSON_OBJECT; - } - else if (object instanceof JSONArray) { - return JSON_ARRAY; - } - else if (object instanceof JsonNode) { - JsonNode node = (JsonNode) object; - JsonNodeType nodeType = node.getNodeType(); - switch (nodeType) { - case ARRAY: - return JACKSON_ARRAY; - case BINARY: - return JACKSON_BINARY; - case BOOLEAN: - return JACKSON_BOOLEAN; - case MISSING: - return JACKSON_MISSING; - case NULL: - return JACKSON_NULL; - case NUMBER: - return JACKSON_NUMBER; - case OBJECT: - return JACKSON_OBJECT; - case POJO: - return JACKSON_POJO; - case STRING: - return JACKSON_STRING; - } - throw new IllegalStateException("unknown node type"); - } - else if (object instanceof Map) { - return MAP; - } - else if (object instanceof Boolean) { - return BOOLEAN; - } - else if (object instanceof List) { - return LIST; - } - else if (object instanceof byte[]) { - return BYTE_ARRAY; - } - else { - return UNKNOWN; - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java b/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java deleted file mode 100644 index 86fa08a7d9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/BinaryParser.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.ripple.core.serialized; - -import com.ripple.core.fields.Field; -import com.ripple.encodings.common.B16; - -public class BinaryParser { - protected final int size; - protected byte[] bytes; - protected int cursor = 0; - - public BinaryParser(byte[] bytes) { - this.size = bytes.length; - this.bytes = bytes; - } - - public BinaryParser(int size) { - this.size = size; - } - - public BinaryParser(String hex) { - this(B16.decode(hex)); - } - - public void skip(int n) { - cursor += n; - } - public byte readOne() { - return bytes[cursor++]; - } - public byte[] read(int n) { - byte[] ret = new byte[n]; - System.arraycopy(bytes, cursor, ret, 0, n); - cursor += n; -// } - return ret; - } - - public Field readField() { - int fieldCode = readFieldCode(); - Field field = Field.fromCode(fieldCode); - if (field == null) { - throw new IllegalStateException("Couldn't parse field from " + - Integer.toHexString(fieldCode)); - } - return field; - } - - public int readFieldCode() { - byte tagByte = readOne(); - - int typeBits = (tagByte & 0xFF) >>> 4; - if (typeBits == 0) typeBits = readOne(); - - int fieldBits = tagByte & 0x0F; - if (fieldBits == 0) fieldBits = readOne(); - - return (typeBits << 16 | fieldBits); - } - - public boolean end() { - return cursor >= size; // greater guard against infinite loops - } - - public int pos() { - return cursor; - } - - public int readOneInt() { - return readOne() & 0xFF; - } - - public int readVLLength() { - int b1 = readOneInt(); - int result; - - if (b1 <= 192) { - result = b1; - } else if (b1 <= 240) { - int b2 = readOneInt(); - result = 193 + (b1 - 193) * 256 + b2; - } else if (b1 <= 254) { - int b2 = readOneInt(); - int b3 = readOneInt(); - result = 12481 + (b1 - 241) * 65536 + b2 * 256 + b3; - } else { - throw new RuntimeException("Invalid varint length indicator"); - } - - return result; - } - - public int size() { - return size; - } - - public boolean end(Integer customEnd) { - return cursor >= size || customEnd != null && cursor >= customEnd; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java b/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java deleted file mode 100644 index 1b39a2ac10..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/BinarySerializer.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.ripple.core.serialized; - -import com.ripple.core.fields.Field; -import com.ripple.core.fields.Type; - -import java.util.Arrays; - -public class BinarySerializer { - private final BytesSink sink; - - public BinarySerializer(BytesSink sink) { - this.sink = sink; - } - - public void add(byte[] n) { - sink.add(n); - } - - public void addLengthEncoded(byte[] n) { - add(encodeVL(n.length)); - add(n); - } - - public static byte[] encodeVL(int length) { - // TODO: bytes - byte[] lenBytes = new byte[4]; - - if (length <= 192) - { - lenBytes[0] = (byte) (length); - return Arrays.copyOf(lenBytes, 1); - } - else if (length <= 12480) - { - length -= 193; - lenBytes[0] = (byte) (193 + (length >>> 8)); - lenBytes[1] = (byte) (length & 0xff); - return Arrays.copyOf(lenBytes, 2); - } - else if (length <= 918744) { - length -= 12481; - lenBytes[0] = (byte) (241 + (length >>> 16)); - lenBytes[1] = (byte) ((length >> 8) & 0xff); - lenBytes[2] = (byte) (length & 0xff); - return Arrays.copyOf(lenBytes, 3); - } else { - throw new RuntimeException("Overflow error"); - } - } - - public void add(BytesList bl) { - for (byte[] bytes : bl.rawList()) { - sink.add(bytes); - } - } - - public int addFieldHeader(Field f) { - if (!f.isSerialized()) { - throw new IllegalStateException(String.format("Field %s is a discardable field", f)); - } - byte[] n = f.getBytes(); - add(n); - return n.length; - } - - public void add(byte type) { - sink.add(type); - } - - public void addLengthEncoded(BytesList bytes) { - add(encodeVL(bytes.bytesLength())); - add(bytes); - } - - public void add(Field field, SerializedType value) { - addFieldHeader(field); - if (field.isVLEncoded()) { - addLengthEncoded(value); - } else { - value.toBytesSink(sink); - if (field.getType() == Type.STObject) { - addFieldHeader(Field.ObjectEndMarker); - } else if (field.getType() == Type.STArray) { - addFieldHeader(Field.ArrayEndMarker); - } - } - } - - public void addLengthEncoded(SerializedType value) { - BytesList bytes = new BytesList(); - value.toBytesSink(bytes); - addLengthEncoded(bytes); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java b/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java deleted file mode 100644 index 69d150aa16..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/BytesList.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ripple.core.serialized; - -import java.security.MessageDigest; -import java.util.ArrayList; - -public class BytesList implements BytesSink { - private ArrayList buffer = new ArrayList(); - - private int len = 0; - - public void add(BytesList bl) { - for (byte[] bytes : bl.rawList()) { - add(bytes); - } - } - - @Override - public void add(byte aByte) { - add(new byte[]{aByte}); - } - - @Override - public void add(byte[] bytes) { - len += bytes.length; - buffer.add(bytes); - } - - public byte[] bytes() { - int n = bytesLength(); - byte[] bytes = new byte[n]; - addBytes(bytes, 0); - return bytes; - } - - static public String[] hexLookup = new String[256]; - static { - for (int i = 0; i < 256; i++) { - String s = Integer.toHexString(i).toUpperCase(); - if (s.length() == 1) { - s = "0" + s; - } - hexLookup[i] = s; - } - } - - public String bytesHex() { - StringBuilder builder = new StringBuilder(len * 2); - for (byte[] buf : buffer) { - for (byte aBytes : buf) { - builder.append(hexLookup[aBytes & 0xFF]); - } - } - return builder.toString(); - } - - public int bytesLength() { - return len; - } - - private int addBytes(byte[] bytes, int destPos) { - for (byte[] buf : buffer) { - System.arraycopy(buf, 0, bytes, destPos, buf.length); - destPos += buf.length; - } - return destPos; - } - - public void updateDigest(MessageDigest digest) { - for (byte[] buf : buffer) { - digest.update(buf); - } - } - - public ArrayList rawList() { - return buffer; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java deleted file mode 100644 index 7ec5c6cc5a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/BytesSink.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ripple.core.serialized; - -public interface BytesSink { - default void add(byte aByte) { - add(new byte[] {aByte}); - } - void add(byte[] bytes); -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java deleted file mode 100644 index 02de05e311..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/MultiSink.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ripple.core.serialized; - -public class MultiSink implements BytesSink { - final private BytesSink[] sinks; - public MultiSink(BytesSink... sinks) { - this.sinks = sinks; - } - @Override - public void add(byte b) { - for (BytesSink sink : sinks) sink.add(b); - } - @Override - public void add(byte[] b) { - for (BytesSink sink : sinks) sink.add(b); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java b/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java deleted file mode 100644 index 1b5263e935..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/SerializedType.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ripple.core.serialized; - -import com.ripple.core.fields.Type; - -public interface SerializedType { - Object toJSON(); - byte[] toBytes(); - String toHex(); - void toBytesSink(BytesSink to); - Type type(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java b/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java deleted file mode 100644 index b3f964c31d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/StreamBinaryParser.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.ripple.core.serialized; - -import java.io.*; -import java.util.zip.GZIPInputStream; - -public class StreamBinaryParser extends BinaryParser { - final BufferedInputStream stream; - - public StreamBinaryParser(InputStream stream, long size) { - super((int) size); - this.stream = new BufferedInputStream(stream); - } - - private static boolean isGZip(File fio) { - return fio.getName().endsWith("gz"); - } - private static int getUncompressedSize(File fio) { - if (isGZip(fio)) { - int val; - try { - RandomAccessFile raf = new RandomAccessFile(fio, "r"); - raf.seek(raf.length() - 4); - int b4 = raf.read(); - int b3 = raf.read(); - int b2 = raf.read(); - int b1 = raf.read(); - val = (b1 << 24) | (b2 << 16) + (b3 << 8) + b4; - raf.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return val; - } else { - return (int) fio.length(); - } - } - - public void skip(int n) { - try { - long skipped = stream.skip(n); - if (skipped != n) { - throw new RuntimeException("Expected to skip more bytes"); - } - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - public byte readOne() { - return read(1)[0]; - } - public byte[] read(int n) { - byte[] ret = new byte[n]; - try { - int read = stream.read(ret); - if (read != n) { - throw new RuntimeException("Expected to read more bytes"); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - cursor += n; - return ret; - } - public static StreamBinaryParser fromFile(String path) { - try { - File f = new File(path); - FileInputStream fstream = new FileInputStream(path); - InputStream stream = fstream; - long s = fstream.getChannel().size(); - - if (isGZip(f)) { - s = getUncompressedSize(f); - stream = new GZIPInputStream(fstream); - } - return new StreamBinaryParser(stream, s); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java b/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java deleted file mode 100644 index 34fe16d377..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/StreamSink.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.ripple.core.serialized; - -import java.io.IOException; -import java.io.OutputStream; - -public class StreamSink implements BytesSink { - OutputStream out; - - public StreamSink(OutputStream out) { - this.out = out; - } - - @Override - public void add(byte aByte) { - try { - out.write(aByte); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void add(byte[] bytes) { - try { - out.write(bytes); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} - diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java b/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java deleted file mode 100644 index 4bd988338b..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/TypeTranslator.java +++ /dev/null @@ -1,151 +0,0 @@ - -package com.ripple.core.serialized; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.runtime.Value; -import com.ripple.encodings.common.B16; -import org.json.JSONArray; -import org.json.JSONObject; - -/** - * @param The SerializedType class - * TODO, this should only really have methods that each class over-rides - * it's currently pretty NASTY - */ -public abstract class TypeTranslator { - - @SuppressWarnings("unchecked") - public T fromValue(Object object) { - switch (Value.typeOf(object)) { - case STRING: - return fromString((String) object); - case JACKSON_ARRAY: - return fromJacksonArray((ArrayNode) object); - case JACKSON_BINARY: - throw new IllegalStateException("cant handle jackson binary"); - case JACKSON_BOOLEAN: - return fromBoolean(((JsonNode) object).asBoolean()); - case JACKSON_MISSING: - throw new IllegalStateException("cant create from missing"); - case JACKSON_NULL: - throw new IllegalStateException("cant create from null"); - case JACKSON_NUMBER: - JsonNode node = (JsonNode) object; - if (node.isLong()) { - return fromLong(node.asLong()); - } else if (node.isInt()) { - return fromInteger(node.asInt()); - } else if (node.isDouble()) { - return fromDouble(node.asDouble()); - } else if (node.isFloat()) { - return fromDouble(node.floatValue()); - } - throw new IllegalStateException("cant create from null"); - case JACKSON_OBJECT: - return fromJacksonObject((ObjectNode) object); - case JACKSON_POJO: - throw new IllegalStateException("cant handle POJO"); - case JACKSON_STRING: - return fromString(((JsonNode) object).asText()); - case DOUBLE: - return fromDouble((Double) object); - case INTEGER: - return fromInteger((Integer) object); - case LONG: - return fromLong((Long) object); - case BOOLEAN: - return fromBoolean((Boolean) object); - case JSON_ARRAY: - return fromJSONArray((JSONArray) object); - case JSON_OBJECT: - return fromJSONObject((JSONObject) object); - case BYTE_ARRAY: - return fromBytes((byte[]) object); - case UNKNOWN: - default: - return (T) object; - } - - } - - protected T fromJacksonObject(ObjectNode object) { - throw new UnsupportedOperationException(); - } - - protected T fromJacksonArray(ArrayNode node) { - throw new UnsupportedOperationException(); - } - - public String toString(T obj) { - return obj.toString(); - } - - protected T fromJSONObject(JSONObject jsonObject) { - throw new UnsupportedOperationException(); - } - - protected T fromJSONArray(JSONArray jsonArray) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("WeakerAccess") - protected T fromBoolean(boolean aBoolean) { - throw new UnsupportedOperationException(); - } - - protected T fromLong(long aLong) { - throw new UnsupportedOperationException(); - } - - protected T fromInteger(int integer) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("WeakerAccess") - protected T fromDouble(double aDouble) { - throw new UnsupportedOperationException(); - } - - protected T fromString(String value) { - throw new UnsupportedOperationException(); - } - - /** - * @param hint Using a boxed integer, allowing null for no hint - */ - public abstract T fromParser(BinaryParser parser, Integer hint); - - public T fromParser(BinaryParser parser) { - return fromParser(parser, null); - } - - public T fromBytes(byte[] b) { - return fromParser(new BinaryParser(b)); - } - - public T fromHex(String hex) { - return fromBytes(B16.decode(hex)); - } - - public Object toJSON(T obj) { - return obj.toJSON(); - } - - public void toBytesSink(T obj, BytesSink to) { - obj.toBytesSink(to); - } - - public byte[] toBytes(T obj) { - BytesList to = new BytesList(); - toBytesSink(obj, to); - return to.bytes(); - } - - public String toHex(T obj) { - BytesList to = new BytesList(); - toBytesSink(obj, to); - return to.bytesHex(); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java deleted file mode 100644 index dafd5d761a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/enums/EngineResult.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.ripple.core.serialized.enums; - -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; - -import java.util.TreeMap; - -class Holder { - public static int ords = 0; -} - -public enum EngineResult implements SerializedType { - telLOCAL_ERROR(-399, "Local failure."), - telBAD_DOMAIN("Domain too long."), - telBAD_PATH_COUNT("Malformed: Too many paths."), - telBAD_PUBLIC_KEY("Public key too long."), - telFAILED_PROCESSING("Failed to correctly process transaction."), - telINSUF_FEE_P("Fee insufficient."), - telNO_DST_PARTIAL("Partial payment to create account not allowed."), - - telCAN_NOT_QUEUE("Can not queue at this time."), - telCAN_NOT_QUEUE_BALANCE("Can not queue at this time: insufficient balance to pay all queued fees."), - telCAN_NOT_QUEUE_BLOCKS("Can not queue at this time: would block later queued transaction(s)."), - - telCAN_NOT_QUEUE_BLOCKED("Can not queue at this time: blocking transaction in queue."), - telCAN_NOT_QUEUE_FEE("Can not queue at this time: fee insufficient to replace queued transaction."), - telCAN_NOT_QUEUE_FULL("Can not queue at this time: queue is full."), - - temMALFORMED(-299, "Malformed transaction."), - temBAD_AMOUNT("Can only send positive amounts."), - temBAD_CURRENCY("Malformed: Bad currency."), - temBAD_EXPIRATION("Malformed: Bad expiration."), - temBAD_FEE("Invalid fee, negative or not XRP."), - temBAD_ISSUER("Malformed: Bad issuer."), - temBAD_LIMIT("Limits must be non-negative."), - temBAD_OFFER("Malformed: Bad offer."), - temBAD_PATH("Malformed: Bad path."), - temBAD_PATH_LOOP("Malformed: Loop in path."), - temBAD_SEND_XRP_LIMIT("Malformed: Limit quality is not allowed for XRP to XRP."), - temBAD_SEND_XRP_MAX("Malformed: Send max is not allowed for XRP to XRP."), - temBAD_SEND_XRP_NO_DIRECT("Malformed: No Ripple direct is not allowed for XRP to XRP."), - temBAD_SEND_XRP_PARTIAL("Malformed: Partial payment is not allowed for XRP to XRP."), - temBAD_SEND_XRP_PATHS("Malformed: Paths are not allowed for XRP to XRP."), - temBAD_SEQUENCE("Malformed: Sequence is not in the past."), - temBAD_SIGNATURE("Malformed: Bad signature."), - temBAD_SRC_ACCOUNT("Malformed: Bad source account."), - temBAD_TRANSFER_RATE("Malformed: Transfer rate must be >= 1.0 and <= 2.0"), - temDST_IS_SRC("Destination may not be source."), - temDST_NEEDED("Destination not specified."), - temINVALID("The transaction is ill-formed."), - temINVALID_FLAG("The transaction has an invalid flag."), - temREDUNDANT("Sends same currency to self."), - temRIPPLE_EMPTY("PathSet with no paths."), - temDISABLED("The transaction requires logic that is currently disabled."), - temBAD_SIGNER("Malformed: No signer may duplicate account or other signers."), - temBAD_QUORUM("Malformed: Quorum is unreachable."), - temBAD_WEIGHT("Malformed: Weight must be a positive value."), - temBAD_TICK_SIZE("Malformed: Tick size out of range."), - temINVALID_ACCOUNT_ID("Malformed: A field contains an invalid account ID."), - temCANNOT_PREAUTH_SELF("Malformed: An account may not preauthorize itself."), - temUNCERTAIN("In process of determining result. Never returned."), - temUNKNOWN(-266, "The transaction requires logic that is not implemented yet."), - - tefFAILURE(-199, "Failed to apply."), - tefALREADY("The exact transaction was already in this ledger."), - tefBAD_ADD_AUTH("Not authorized to add account."), - tefBAD_AUTH("Transaction's public key is not authorized."), - tefBAD_LEDGER("Ledger in unexpected state."), - tefCREATED("Can't add an already created account."), - tefEXCEPTION("Unexpected program state."), - tefINTERNAL("Internal error."), - tefNO_AUTH_REQUIRED("Auth is not required."), - tefPAST_SEQ("This sequence number has already passed."), - tefWRONG_PRIOR("This previous transaction does not match."), - tefMASTER_DISABLED("Master key is disabled."), - tefMAX_LEDGER("Ledger sequence too high."), - tefBAD_SIGNATURE("A signature is provided for a non-signer."), - tefBAD_QUORUM("Signatures provided do not meet the quorum."), - tefNOT_MULTI_SIGNING("Account has no appropriate list of multi-signers."), - tefBAD_AUTH_MASTER("Auth for unclaimed account needs correct master key."), - tefINVARIANT_FAILED("Fee claim violated invariants for the transaction."), - - - - - terRETRY(-99, "Retry transaction."), - terFUNDS_SPENT("Can't set password, password set funds already spent."), - terINSUF_FEE_B("Account balance can't pay fee."), - terNO_ACCOUNT("The source account does not exist."), - terNO_AUTH("Not authorized to hold IOUs."), - terNO_LINE("No such line."), - terOWNERS("Non-zero owner count."), - terPRE_SEQ("Missing/inapplicable prior transaction."), - terLAST("Process last."), - terNO_RIPPLE("Path does not permit rippling."), - terQUEUED("Held until escalated fee drops."), - - tesSUCCESS(0, "The transaction was applied. Only final in a validated ledger."), - - tecCLAIM(100, "Fee claimed. Sequence used. No action."), - tecPATH_PARTIAL(101, "Path could not send full amount."), - tecUNFUNDED_ADD(102, "Insufficient XRP balance for WalletAdd."), - tecUNFUNDED_OFFER(103, "Insufficient balance to fund created offer."), - tecUNFUNDED_PAYMENT(104, "Insufficient XRP balance to send."), - tecFAILED_PROCESSING(105, "Failed to correctly process transaction."), - tecDIR_FULL(121, "Can not add entry to full directory."), - tecINSUF_RESERVE_LINE(122, "Insufficient reserve to add trust line."), - tecINSUF_RESERVE_OFFER(123, "Insufficient reserve to create offer."), - tecNO_DST(124, "Destination does not exist. Send XRP to create it."), - tecNO_DST_INSUF_XRP(125, "Destination does not exist. Too little XRP sent to create it."), - tecNO_LINE_INSUF_RESERVE(126, "No such line. Too little reserve to create it."), - tecNO_LINE_REDUNDANT(127, "Can't set non-existent line to default."), - tecPATH_DRY(128, "Path could not send partial amount."), - tecUNFUNDED(129, "One of _ADD, _OFFER, or _SEND. Deprecated."), - tecNO_ALTERNATIVE_KEY(130, "The operation would remove the ability to sign transactions with the account."), - tecNO_REGULAR_KEY(131, "Regular key is not set."), - tecOWNERS(132, "Non-zero owner count."), - tecNO_ISSUER(133, "Issuer account does not exist."), - tecNO_AUTH(134, "Not authorized to hold asset."), - tecNO_LINE(135, "No such line."), - tecINSUFF_FEE(136, "Insufficient balance to pay fee."), - tecFROZEN(137, "Asset is frozen."), - tecNO_TARGET(138, "Target account does not exist."), - tecNO_PERMISSION(139, "No permission to perform requested operation."), - tecNO_ENTRY(140, "No matching entry found."), - tecINSUFFICIENT_RESERVE(141, "Insufficient reserve to complete requested operation."), - tecNEED_MASTER_KEY(142, "The operation requires the use of the Master Key."), - tecDST_TAG_NEEDED(143, "A destination tag is required."), - tecINTERNAL(144, "An internal error has occurred during processing."), - tecOVERSIZE(145, "Object exceeded serialization limits."), - tecCRYPTOCONDITION_ERROR(146, "Malformed, invalid, or mismatched conditional or fulfillment."), - tecINVARIANT_FAILED(147, "One or more invariants for the transaction were not satisfied."), - tecEXPIRED(148, "Expiration time is passed."), - tecDUPLICATE(149, "Ledger object already exists."), - tecKILLED(150, "FillOrKill offer killed."), - ; - - - public int asInteger() { - return ord; - } - - @Override - public Type type() { - return Type.UInt8; - } - - private static int ords = 0; - int ord; - public String human; - EngineResult class_ = null; - - EngineResult(Integer i, String s) { - human = s; - if (i == null) { - i = ++Holder.ords; - } else { - Holder.ords = i; - } - ord = i; - } - - EngineResult(String s) { - this(null, s); - } - - private static TreeMap byCode; - - static { - byCode = new TreeMap<>(); - for (EngineResult ter : EngineResult.values()) { - byCode.put(ter.ord, ter); - } - } - - public static EngineResult fromNumber(Number i) { - return byCode.get(i.intValue()); - } - - - /*Serialized Type implementation*/ - @Override - public byte[] toBytes() { - return new byte[]{(byte) ord}; - } - - @Override - public void toBytesSink(BytesSink to) { - to.add((byte) ord); - } - - @Override - public Object toJSON() { - return toString(); - } - - @Override - public String toHex() { - return B16.encode(toBytes()); - } - - public static class Translator extends TypeTranslator { - @Override - public EngineResult fromParser(BinaryParser parser, Integer hint) { - return fromInteger(parser.readOneInt()); - } - - @Override - public EngineResult fromString(String value) { - return EngineResult.valueOf(value); - } - - @Override - public EngineResult fromInteger(int integer) { - return fromNumber(integer); - } - } - - @SuppressWarnings("unused") - public static Translator translate = new Translator(); - - // Result Classes - public static EngineResult resultClass(EngineResult result) { - if (result.ord >= telLOCAL_ERROR.ord && result.ord < temMALFORMED.ord) { - return telLOCAL_ERROR; - } - if (result.ord >= temMALFORMED.ord && result.ord < tefFAILURE.ord) { - return temMALFORMED; - } - if (result.ord >= tefFAILURE.ord && result.ord < terRETRY.ord) { - return tefFAILURE; - } - if (result.ord >= terRETRY.ord && result.ord < tesSUCCESS.ord) { - return terRETRY; - } - if (result.ord >= tesSUCCESS.ord && result.ord < tecCLAIM.ord) { - return tesSUCCESS; - } - return tecCLAIM; - } - - public EngineResult resultClass() { - return class_; - } - - static { - for (EngineResult engineResult : EngineResult.values()) { - engineResult.class_ = resultClass(engineResult); - } - } - -} - - diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java deleted file mode 100644 index cba003d2d9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/enums/LedgerEntryType.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.ripple.core.serialized.enums; - -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -public enum LedgerEntryType implements SerializedType { - // Invalid (-1), - AccountRoot('a'), - DirectoryNode('d'), - // GeneratorMap ('g'), - RippleState('r'), - Escrow('u'), - // Nickname ('n'), // deprecated - Offer('o'), - // Contract ('c'), - LedgerHashes('h'), - Amendments('f'), - FeeSettings('s'), - Ticket('T'), - SignerList('S'), - PayChannel('x'), - Check('C'), - DepositPreauth('p'); - - final int ord; - - LedgerEntryType(int i) { - ord = i; - } - - static private Map byCode = new TreeMap<>(); - - static { - for (Object a : LedgerEntryType.values()) { - LedgerEntryType f = (LedgerEntryType) a; - byCode.put(f.ord, f); - } - } - - @Override - public Type type() { - return Type.UInt16; - } - - public static LedgerEntryType fromNumber(Number i) { - return byCode.get(i.intValue()); - } - - public Integer asInteger() { - return ord; - } - - // SeralizedType interface - @Override - public byte[] toBytes() { - return new byte[]{(byte) ((ord >>> 8) & 0xFF), (byte) (ord & 0xFF)}; - } - - @Override - public Object toJSON() { - return toString(); - } - - @Override - public String toHex() { - return B16.encode(toBytes()); - } - - @Override - public void toBytesSink(BytesSink to) { - to.add(toBytes()); - } - - public static class Translator extends TypeTranslator { - @Override - public LedgerEntryType fromParser(BinaryParser parser, Integer hint) { - return fromNumber(parser.readOneInt() << 8 | parser.readOneInt()); - } - - @Override - public LedgerEntryType fromInteger(int integer) { - return fromNumber(integer); - } - - @Override - public LedgerEntryType fromString(String value) { - return LedgerEntryType.valueOf(value); - } - } - - @SuppressWarnings("unused") - public static Translator translate = new Translator(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java b/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java deleted file mode 100644 index 7c98c3da07..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/serialized/enums/TransactionType.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.ripple.core.serialized.enums; - -import com.ripple.core.fields.Type; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.TypeTranslator; -import com.ripple.encodings.common.B16; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -public enum TransactionType implements SerializedType { - // Invalid (-1), - Payment (0), - EscrowCreate (1), // open - EscrowFinish (2), - AccountSet (3), // open, - EscrowCancel (4), - SetRegularKey(5), - // unused1 (6), // open - OfferCreate (7), - OfferCancel (8), - // unused2(9), - TicketCreate(10), - TicketCancel(11), - SignerListSet(12), - PaymentChannelCreate(13), - PaymentChannelFund(14), - PaymentChannelClaim(15), - CheckCreate(16), - CheckCash(17), - CheckCancel(18), - DepositPreauth(19), - TrustSet (20), - EnableAmendment(100), - SetFee(101); - - public int asInteger() { - return ord; - } - - final int ord; - TransactionType(int i) { - ord = i; - } - - @Override - public Type type() { - return Type.UInt16; - } - - static private Map byCode = new TreeMap<>(); - static { - for (Object a : TransactionType.values()) { - TransactionType f = (TransactionType) a; - byCode.put(f.ord, f); - } - } - - static public TransactionType fromNumber(Number i) { - return byCode.get(i.intValue()); - } - - // SeralizedType interface - @Override - public byte[] toBytes() { - // TODO: bytes - return new byte[]{(byte) (ord >> 8), (byte) (ord & 0xFF)}; - } - @Override - public Object toJSON() { - return toString(); - } - @Override - public String toHex() { - return B16.encode(toBytes()); - } - @Override - public void toBytesSink(BytesSink to) { - to.add(toBytes()); - } - public static class Translator extends TypeTranslator { - @Override - public TransactionType fromParser(BinaryParser parser, Integer hint) { - return fromNumber(parser.readOneInt() << 8 | parser.readOneInt()); - } - - @Override - public TransactionType fromInteger(int integer) { - return fromNumber(integer); - } - - @Override - public TransactionType fromString(String value) { - return TransactionType.valueOf(value); - } - } - - @SuppressWarnings("unused") - public static Translator translate = new Translator(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java b/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java deleted file mode 100644 index f7efd08ed2..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/generic/Validation.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ripple.core.types.known.generic; - -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; - -public class Validation extends STObject { - public static boolean isValidation(STObject source) { - return source.has(UInt32.LedgerSequence) && - source.has(UInt32.SigningTime) && - source.has(Hash256.LedgerHash) && - source.has(Blob.Signature); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java deleted file mode 100644 index c5dc3f7f3d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerEntry.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.ripple.core.types.known.sle; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.formats.LEFormat; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.entries.AccountRoot; -import com.ripple.core.types.known.sle.entries.DirectoryNode; -import com.ripple.core.types.known.sle.entries.Offer; -import com.ripple.core.types.known.sle.entries.RippleState; - -import java.util.TreeSet; - -public class LedgerEntry extends STObject { - public LedgerEntry(LedgerEntryType type) { - setFormat(LEFormat.formats.get(type)); - put(Field.LedgerEntryType, type); - } - - public LedgerEntryType ledgerEntryType() {return ledgerEntryType(this);} - public Hash256 index() { return get(Hash256.index); } - public UInt32 flags() {return get(UInt32.Flags);} - public Hash256 ledgerIndex() {return get(Hash256.LedgerIndex);} - - public void flags(UInt32 val) {put(Field.Flags, val);} - public void ledgerIndex(Hash256 val) {put(Field.LedgerIndex, val);} - - public boolean hasLedgerIndex() {return has(Hash256.LedgerIndex);} - - public TreeSet owners() { - TreeSet owners = new TreeSet<>(); - - if (has(Field.LowLimit)) { - owners.add(get(Amount.LowLimit).issuer()); - } - if (has(Field.HighLimit)) { - owners.add(get(Amount.HighLimit).issuer()); - } - if (has(Field.Account)) { - owners.add(get(AccountID.Account)); - } - - return owners; - } - - public void index(Hash256 index) { - put(Hash256.index, index); - } - - public void setDefaults() { - if (flags() == null) { - flags(UInt32.ZERO); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java deleted file mode 100644 index 9b9086cd72..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/LedgerHashes.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ripple.core.types.known.sle; - -import com.ripple.core.coretypes.Vector256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class LedgerHashes extends LedgerEntry { - public LedgerHashes() { - super(LedgerEntryType.LedgerHashes); - } - - public Vector256 hashes() { - return get(Vector256.Hashes); - } - - public void hashes(Vector256 hashes) { - put(Vector256.Hashes, hashes); - } - - public UInt32 lastLedgerSequence() { - return get(UInt32.LastLedgerSequence); - } - - public UInt32 firstLedgerSequence() {return get(UInt32.FirstLedgerSequence);} - - public void firstLedgerSequence(UInt32 val) { put(UInt32.FirstLedgerSequence, val);} - - public void lastLedgerSequence(UInt32 val) { put(UInt32.LastLedgerSequence, val);} - - public boolean hasFirstLedgerSequence() {return has(UInt32.FirstLedgerSequence);} - public boolean hasLastLedgerSequence() {return has(UInt32.LastLedgerSequence);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java deleted file mode 100644 index 3739109d97..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/ThreadedLedgerEntry.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ripple.core.types.known.sle; - - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; - -// this class has a PreviousTxnID and PreviousTxnLgrSeq -abstract public class ThreadedLedgerEntry extends LedgerEntry { - public ThreadedLedgerEntry(LedgerEntryType type) { - super(type); - } - public UInt32 previousTxnLgrSeq() {return get(UInt32.PreviousTxnLgrSeq);} - public Hash256 previousTxnID() {return get(Hash256.PreviousTxnID);} - public void previousTxnLgrSeq(UInt32 val) {put(Field.PreviousTxnLgrSeq, val);} - public void previousTxnID(Hash256 val) {put(Field.PreviousTxnID, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java deleted file mode 100644 index 22f26def99..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/AccountRoot.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.hash.Hash128; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.enums.LedgerFlag; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.ThreadedLedgerEntry; - -public class AccountRoot extends ThreadedLedgerEntry { - public AccountRoot() { - super(LedgerEntryType.AccountRoot); - } - - public UInt32 sequence() {return get(UInt32.Sequence);} - public UInt32 transferRate() {return get(UInt32.TransferRate);} - public UInt32 walletSize() {return get(UInt32.WalletSize);} - public UInt32 ownerCount() {return get(UInt32.OwnerCount);} - public Hash128 emailHash() {return get(Hash128.EmailHash);} - public Hash256 walletLocator() {return get(Hash256.WalletLocator);} - public Amount balance() {return get(Amount.Balance);} - public Blob messageKey() {return get(Blob.MessageKey);} - public Blob domain() {return get(Blob.Domain);} - public AccountID account() {return get(AccountID.Account);} - public AccountID regularKey() {return get(AccountID.RegularKey);} - - public void sequence(UInt32 val) {put(Field.Sequence, val);} - public void transferRate(UInt32 val) {put(Field.TransferRate, val);} - public void walletSize(UInt32 val) {put(Field.WalletSize, val);} - public void ownerCount(UInt32 val) {put(Field.OwnerCount, val);} - public void emailHash(Hash128 val) {put(Field.EmailHash, val);} - public void walletLocator(Hash256 val) {put(Field.WalletLocator, val);} - public void balance(Amount val) {put(Field.Balance, val);} - public void messageKey(Blob val) {put(Field.MessageKey, val);} - public void domain(Blob val) {put(Field.Domain, val);} - public void account(AccountID val) {put(Field.Account, val);} - public void regularKey(AccountID val) {put(Field.RegularKey, val);} - - public boolean requiresAuth() { - return flags().testBit(LedgerFlag.RequireAuth); - } - - public boolean hasAccountTxnID() {return has(Hash256.AccountTxnID);} - public boolean hasDomain() {return has(Blob.Domain);} - public boolean hasEmailHash() {return has(Hash128.EmailHash);} - public boolean hasMessageKey() {return has(Blob.MessageKey);} - public boolean hasRegularKey() {return has(AccountID.RegularKey);} - public boolean hasTickSize() {return has(UInt8.TickSize);} - public boolean hasTransferRate() {return has(UInt32.TransferRate);} - public boolean hasWalletLocator() {return has(Hash256.WalletLocator);} - public boolean hasWalletSize() {return has(UInt32.WalletSize);} - - public Hash256 accountTxnID() {return get(Hash256.AccountTxnID);} - public UInt8 tickSize() {return get(UInt8.TickSize);} - - public void accountTxnID(Hash256 val) { put(Hash256.AccountTxnID, val);} - public void tickSize(UInt8 val) { put(UInt8.TickSize, val);} - - @Override - public void setDefaults() { - super.setDefaults(); - if (ownerCount() == null) { - ownerCount(new UInt32(0)); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java deleted file mode 100644 index 8b580af8ef..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Amendments.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.STArray; -import com.ripple.core.coretypes.Vector256; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.LedgerEntry; - -public class Amendments extends LedgerEntry { - public Amendments() { - super(LedgerEntryType.Amendments); - } - - public STArray majorities() {return get(STArray.Majorities);} - public Vector256 amendments() {return get(Vector256.Amendments);} - - public void amendments(Vector256 val) { put(Vector256.Amendments, val);} - public void majorities(STArray val) { put(STArray.Majorities, val);} - - public boolean hasAmendments() {return has(Vector256.Amendments);} - public boolean hasMajorities() {return has(STArray.Majorities);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java deleted file mode 100644 index 310232b1dd..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Check.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class Check extends IndexedLedgerEntry { - public Check() { - super(LedgerEntryType.Check); - } - - public boolean hasSourceTag() {return has(UInt32.SourceTag);} - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} - - public UInt32 sourceTag() {return get(UInt32.SourceTag);} - public UInt32 sequence() {return get(UInt32.Sequence);} - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - public UInt64 destinationNode() {return get(UInt64.DestinationNode);} - public Hash256 invoiceID() {return get(Hash256.InvoiceID);} - public Amount sendMax() {return get(Amount.SendMax);} - public AccountID account() {return get(AccountID.Account);} - public AccountID destination() {return get(AccountID.Destination);} - - public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} - public void sequence(UInt32 val) { put(UInt32.Sequence, val);} - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - public void destinationNode(UInt64 val) { put(UInt64.DestinationNode, val);} - public void invoiceID(Hash256 val) { put(Hash256.InvoiceID, val);} - public void sendMax(Amount val) { put(Amount.SendMax, val);} - public void destination(AccountID val) { put(AccountID.Destination, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java deleted file mode 100644 index 7f995ecc1c..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DepositPreauthLe.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class DepositPreauthLe extends IndexedLedgerEntry { - public DepositPreauthLe() { - super(LedgerEntryType.DepositPreauth); - } - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - - public AccountID account() {return get(AccountID.Account);} - - public AccountID authorize() {return get(AccountID.Authorize);} - public void authorize(AccountID val) { put(AccountID.Authorize, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java deleted file mode 100644 index f46a7d7973..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/DirectoryNode.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Currency; -import com.ripple.core.coretypes.Vector256; -import com.ripple.core.coretypes.hash.Hash160; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.LedgerEntry; - -public class DirectoryNode extends LedgerEntry { - public DirectoryNode() { - super(LedgerEntryType.DirectoryNode); - } - - public UInt64 indexNext() {return get(UInt64.IndexNext);} - public UInt64 indexPrevious() {return get(UInt64.IndexPrevious);} - public UInt64 exchangeRate() {return get(UInt64.ExchangeRate);} - public Hash256 rootIndex() {return get(Hash256.RootIndex);} - public AccountID owner() {return get(AccountID.Owner);} - public Hash160 takerPaysCurrency() {return get(Hash160.TakerPaysCurrency);} - public Hash160 takerPaysIssuer() {return get(Hash160.TakerPaysIssuer);} - public Hash160 takerGetsCurrency() {return get(Hash160.TakerGetsCurrency);} - public Hash160 takerGetsIssuer() {return get(Hash160.TakerGetsIssuer);} - public Vector256 indexes() {return get(Vector256.Indexes);} - public void indexNext(UInt64 val) {put(Field.IndexNext, val);} - public void indexPrevious(UInt64 val) {put(Field.IndexPrevious, val);} - public void exchangeRate(UInt64 val) {put(Field.ExchangeRate, val);} - public void rootIndex(Hash256 val) {put(Field.RootIndex, val);} - public void owner(AccountID val) {put(Field.Owner, val);} - public void takerPaysCurrency(Hash160 val) {put(Field.TakerPaysCurrency, val);} - public void takerPaysIssuer(Hash160 val) {put(Field.TakerPaysIssuer, val);} - public void takerGetsCurrency(Hash160 val) {put(Field.TakerGetsCurrency, val);} - public void takerGetsIssuer(Hash160 val) {put(Field.TakerGetsIssuer, val);} - public void indexes(Vector256 val) {put(Field.Indexes, val);} - - public boolean hasIndexNext() {return has(UInt64.IndexNext);} - public boolean hasIndexPrevious() {return has(UInt64.IndexPrevious);} - public boolean hasExchangeRate() {return has(UInt64.ExchangeRate);} - public boolean hasOwner() {return has(AccountID.Owner);} - public boolean hasTakerPaysCurrency() {return has(Hash160.TakerPaysCurrency);} - public boolean hasTakerPaysIssuer() {return has(Hash160.TakerPaysIssuer);} - public boolean hasTakerGetsCurrency() {return has(Hash160.TakerGetsCurrency);} - public boolean hasTakerGetsIssuer() {return has(Hash160.TakerGetsIssuer);} - - public Hash256 nextIndex() { - return Index.directoryNode(rootIndex(), indexNext()); - } - public Hash256 prevIndex() { - return Index.directoryNode(rootIndex(), indexPrevious()); - } - - public boolean hasPreviousIndex() { - return hasIndexPrevious() && !indexPrevious().isZero(); - } - - public boolean hasNextIndex() { - return hasIndexNext() && !indexNext().isZero(); - } - - public boolean isRootIndex() { - return rootIndex().equals(index()); - } - - public void setExchangeDefaults() { - if (takerGetsCurrency() == null) { - takerGetsCurrency(Currency.XRP); - takerGetsIssuer(AccountID.XRP_ISSUER); - } else if (takerPaysCurrency() == null) { - takerPaysCurrency(Currency.XRP); - takerPaysIssuer(AccountID.XRP_ISSUER); - } - } - - @Override - public void setDefaults() { - super.setDefaults(); - if (exchangeRate() != null) { - setExchangeDefaults(); - } - if (indexes() == null) { - indexes(new Vector256()); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java deleted file mode 100644 index ff822c6757..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Escrow.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.tx.Transaction; - -import java.util.ArrayList; - -public class Escrow extends IndexedLedgerEntry { - public Escrow() { - super(LedgerEntryType.Escrow); - } - - @Override - public void setDefaults() { - super.setDefaults(); - if (multiParty()) { - if (!has(UInt64.DestinationNode)) { - put(UInt64.DestinationNode, UInt64.ZERO); - } - } - } - - @Override - public ArrayList ownerDirectoryIndexes(Transaction nullableContext) { - ArrayList indexes = super.ownerDirectoryIndexes(nullableContext); - if (multiParty()) { - Hash256 destinationOwnerDir = - Index.ownerDirectory(destination()); - indexes.add(Index.directoryNode( - destinationOwnerDir, destinationNode())); - } - return indexes; - } - - private boolean multiParty() { - return !get(AccountID.Account).equals(destination()); - } - - public AccountID account() {return get(AccountID.Account);} - public AccountID destination() {return get(AccountID.Destination);} - public Amount amount() {return get(Amount.Amount);} - public Blob condition() {return get(Blob.Condition);} - public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public UInt32 finishAfter() {return get(UInt32.FinishAfter);} - public UInt32 sourceTag() {return get(UInt32.SourceTag);} - public UInt64 destinationNode() {return get(UInt64.DestinationNode);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - - public void amount(Amount val) { put(Amount.Amount, val);} - public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} - public void condition(Blob val) { put(Blob.Condition, val);} - public void destination(AccountID val) { put(AccountID.Destination, val);} - public void destinationNode(UInt64 val) { put(UInt64.DestinationNode, val);} - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void finishAfter(UInt32 val) { put(UInt32.FinishAfter, val);} - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} - - public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} - public boolean hasCondition() {return has(Blob.Condition);} - public boolean hasDestinationNode() {return has(UInt64.DestinationNode);} - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasFinishAfter() {return has(UInt32.FinishAfter);} - public boolean hasSourceTag() {return has(UInt32.SourceTag);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java deleted file mode 100644 index ce8fca505d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/FeeSettings.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.LedgerEntry; - -public class FeeSettings extends LedgerEntry { - public FeeSettings() { - super(LedgerEntryType.Amendments); - } - public UInt32 referenceFeeUnits() {return get(UInt32.ReferenceFeeUnits);} - public UInt32 reserveBase() {return get(UInt32.ReserveBase);} - public UInt32 reserveIncrement() {return get(UInt32.ReserveIncrement);} - public UInt64 baseFee() {return get(UInt64.BaseFee);} - - public void baseFee(UInt64 val) { put(UInt64.BaseFee, val);} - public void referenceFeeUnits(UInt32 val) { put(UInt32.ReferenceFeeUnits, val);} - public void reserveBase(UInt32 val) { put(UInt32.ReserveBase, val);} - public void reserveIncrement(UInt32 val) { put(UInt32.ReserveIncrement, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java deleted file mode 100644 index 93c15e2f80..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IHasOwners.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.types.known.tx.Transaction; - -import java.util.ArrayList; - -public interface IHasOwners { - ArrayList ownerDirectoryIndexes(Transaction nullableContext); - AccountID account(Transaction nullableContext); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java deleted file mode 100644 index 37ff656961..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/IndexedLedgerEntry.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.ThreadedLedgerEntry; -import com.ripple.core.types.known.tx.Transaction; - -import java.util.ArrayList; - -public abstract class IndexedLedgerEntry extends ThreadedLedgerEntry implements IHasOwners { - public IndexedLedgerEntry(LedgerEntryType type) { - super(type); - } - - @Override - public void setDefaults() { - super.setDefaults(); - if (!has(Field.OwnerNode)) { - put(UInt64.OwnerNode, UInt64.ZERO); - } - } - - @Override - public AccountID account(Transaction nullableContext) { - AccountID account = account(); - if (account == null) { - if (nullableContext != null) { - account = nullableContext.account(); - } else { - throw new IllegalStateException("Cant determine account for: " + prettyJSON()); - } - } - return account; - } - - @Override - public ArrayList ownerDirectoryIndexes(Transaction nullableContext) { - Hash256 ownerDir = Index.ownerDirectory(account(nullableContext)); - ArrayList indexes = new ArrayList<>(); - indexes.add(Index.directoryNode(ownerDir, ownerNode())); - return indexes; - } - - private UInt64 ownerNode() { - return get(UInt64.OwnerNode); - } - - private AccountID account() { - return get(AccountID.Account); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java deleted file mode 100644 index ceaa7a6732..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Offer.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.*; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.ThreadedLedgerEntry; - -import java.math.BigDecimal; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; - -public class Offer extends ThreadedLedgerEntry { - public Offer() { - super(LedgerEntryType.Offer); - } - - /** - * Use the BookDirectory field - * - * @return how much must `pay` to `get` one. - * - */ - public BigDecimal directoryAskQuality() { - return Quality.fromBookDirectory(bookDirectory(), - takerPays().isNative(), - takerGets().isNative()); - } - - /** - * @return how much must `pay` to `get` one. - */ - public BigDecimal askQuality() { - return takerPays().computeQuality(takerGets()); - } - - /** - * @return how much `get` if `pay` one. - */ - public BigDecimal bidQuality() { - return takerGets().computeQuality(takerPays()); - } - - /** - * - * @return One of TakerGets issue, eg 1/USD/BITSTAMP or 1/EUR/SNAPSWAP - */ - public Amount getsOne() { - return takerGets().one(); - } - /** - * - * @return One of TakerPays issue, eg 1/USD/BITSTAMP or 1/EUR/SNAPSWAP - */ - public Amount paysOne() { - return takerPays().one(); - } - - public String getPayCurrencyPair() { - return takerGets().currencyString() + "/" + - takerPays().currencyString(); - } - - // TODO: create an OfferExecution object for this - public STObject executed(STObject finalFields) { - // where `this` is an AffectedNode nodeAsPrevious - STObject executed = new STObject(); - executed.put(Amount.TakerPays, finalFields.get(Amount.TakerPays).subtract(takerPays())); - executed.put(Amount.TakerGets, finalFields.get(Amount.TakerGets).subtract(takerGets())); - return executed; - } - - public Hash256 lineIndex(Amount amt) { - return account().lineIndex(amt.issue()); - } - - public Hash256 fundingSource() { - Amount takerGets = takerGets(); - if (account().equals(takerGets.issuer())) { - return null; - } - else if (takerGets.isNative()) { - return Index.accountRoot(account()); - } else { - return lineIndex(takerGets); - } - } - - public Vector256 lineIndexes() { - Vector256 ret = new Vector256(); - - Amount takerGets = takerGets(); - for (Amount amt : new Amount[]{takerGets, takerPays()}) { - - // Actually want to compare by reference here :) - if (amt == takerGets()) { - // selling own funds - continue; - } - if (!amt.isNative()) { - ret.add(lineIndex(amt)); - } - } - return ret; - } - - public Hash256 bookBase() { - return Index.bookStart(takerPays().issue(), takerGets().issue()); - } - - public boolean belongsToBook(Hash256 bookBase) { - byte[] baseBytes = bookBase.bytes(); - byte[] directoryBytes = bookDirectory().bytes(); - - for (int i = 0; i < 24; i++) { - if (baseBytes[i] != directoryBytes[i]) { - return false; - } - } - return true; - } - - public boolean sellingOwnFunds() { - return account().equals(takerGets().issuer()); - } - - public Amount takerGetsFunded() { - return has(Field.taker_gets_funded) ? get(Amount.taker_gets_funded) : takerGets(); - } - public Amount takerPaysFunded() { - return has(Field.taker_pays_funded) ? get(Amount.taker_pays_funded) : takerPays(); - } - - public static Comparator qualityAscending = Comparator.comparing(Offer::directoryAskQuality); - - public static Iterator iterateCollection(Collection offers) { - final Iterator iterator = offers.iterator(); - - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Offer next() { - return (Offer) iterator.next(); - } - - @Override - public void remove() { - iterator.remove(); - - } - }; - } - - public Hash256 bookNodeDirectoryIndex() { - return Index.directoryNode(bookDirectory(), bookNode()); - } - - public Hash256 ownerNodeDirectoryIndex() { - Hash256 ownerDir = Index.ownerDirectory(account()); - return Index.directoryNode(ownerDir, ownerNode()); - } - - - public UInt32 sequence() {return get(UInt32.Sequence);} - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt64 bookNode() {return get(UInt64.BookNode);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - public Hash256 bookDirectory() {return get(Hash256.BookDirectory);} - public Amount takerPays() {return get(Amount.TakerPays);} - public Amount takerGets() {return get(Amount.TakerGets);} - public AccountID account() {return get(AccountID.Account);} - public void sequence(UInt32 val) {put(Field.Sequence, val);} - public void expiration(UInt32 val) {put(Field.Expiration, val);} - public void bookNode(UInt64 val) {put(Field.BookNode, val);} - public void ownerNode(UInt64 val) {put(Field.OwnerNode, val);} - public void bookDirectory(Hash256 val) {put(Field.BookDirectory, val);} - public void takerPays(Amount val) {put(Field.TakerPays, val);} - public void takerGets(Amount val) {put(Field.TakerGets, val);} - public void account(AccountID val) {put(Field.Account, val);} - - public boolean hasExpiration() {return has(UInt32.Expiration);} - - public Hash256[] directoryIndexes() { - return new Hash256[]{bookNodeDirectoryIndex(), ownerNodeDirectoryIndex()}; - } - - @Override - public void setDefaults() { - super.setDefaults(); - setOfferDefaults(); - } - - public void setOfferDefaults() { - if (bookNode() == null) { - bookNode(UInt64.ZERO); - } - if (ownerNode() == null) { - ownerNode(UInt64.ZERO); - } - } - - public IssuePair issuePair() { - return new IssuePair(takerPays().issue(), takerGets().issue()); - } - - public Amount payToGet(Amount funded) { - BigDecimal quality = directoryAskQuality(); - // Multiply by one as that will do the rounding operation we want - return paysOne().multiply(funded.multiply(quality)); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java deleted file mode 100644 index fddb7126fd..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OfferDirectory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.Issue; -import com.ripple.core.coretypes.IssuePair; - -public class OfferDirectory extends DirectoryNode { - public IssuePair issuePair() { - return new IssuePair(takerPaysIssue(), takerGetsIssue()); - } - - public Issue takerGetsIssue() { - // TODO: remove wrapper - return Issue.from160s(takerGetsCurrency(), takerGetsIssuer()); - } - public Issue takerPaysIssue() { - // TODO: remove wrapper - return Issue.from160s(takerPaysCurrency(), takerPaysIssuer()); - } - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java deleted file mode 100644 index b6f784e4b8..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/OwnerDirectory.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -public class OwnerDirectory extends DirectoryNode { } diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java deleted file mode 100644 index 97a2786b2a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/PayChannel.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class PayChannel extends IndexedLedgerEntry { - public PayChannel() { - super(LedgerEntryType.PayChannel); - } - - public AccountID account() {return get(AccountID.Account);} - public AccountID destination() {return get(AccountID.Destination);} - public Amount amount() {return get(Amount.Amount);} - public Amount balance() {return get(Amount.Balance);} - public Blob publicKey() {return get(Blob.PublicKey);} - public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt32 settleDelay() {return get(UInt32.SettleDelay);} - public UInt32 sourceTag() {return get(UInt32.SourceTag);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - - public void amount(Amount val) { put(Amount.Amount, val);} - public void balance(Amount val) { put(Amount.Balance, val);} - public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} - public void destination(AccountID val) { put(AccountID.Destination, val);} - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - public void publicKey(Blob val) { put(Blob.PublicKey, val);} - public void settleDelay(UInt32 val) { put(UInt32.SettleDelay, val);} - public void sourceTag(UInt32 val) { put(UInt32.SourceTag, val);} - - public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasSourceTag() {return has(UInt32.SourceTag);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java deleted file mode 100644 index 02f9f2ad2e..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/RippleState.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Currency; -import com.ripple.core.coretypes.Issue; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.enums.LedgerFlag; -import com.ripple.core.fields.AmountField; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.ThreadedLedgerEntry; - -import java.util.Arrays; -import java.util.List; - -public class RippleState extends ThreadedLedgerEntry { - /** - The RippleState is a ledger entry which roughly speaking defines the balance and - trust limits between two accounts. - - Like all current ledger entries, it has a canonical form for hashing that - doesn't necessarily communicate the information in a way that is clear or - obvious to a human. The current json format for some ledger entries is very - close to the hashing format, and isn't any better. - - The two accounts on the link are categorized into a low account, and a high - account by comparing the 160bits of their account id as a big endian unsigned - integer. - - There is one and only one `Balance` stored, using an amount struct with a - neutral `issuer`. ( A uint160 with the numerical value of `1` was chosen as a - placeholder, as the canonical way to represent a null account ) - - The Balance can be negative, zero, or positive and is in terms of the Low - account, such that when it's positive, it defines how much credit the High - account has issued. - - Between any account, there can be two types of balance changes, issuance and - redemption. A redemption is the transferal of previously issued IOUs back to the - owner. - - This implies that for any account, that can they can make a transferal using - funds from two distinct balances. After making this distinction it becomes - nonsensical to say that an account holds negative IOUs from the opposite line. - - Thus, the one Balance in a ripple state actually implies 4 distinct balances. - - ``` - { - ... - "Balance" : { - "currency" : "USD", - "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji", - "value" : "100" - }, - "HighLimit" : { - "currency" : "USD", - "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK", - "value" : "500" - }, - "LowLimit" : { - "currency" : "USD", - "issuer" : "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "value" : "500" - }, - } - ``` - - lowAccount = LowLimit.issuer - hiAccount = HighLimit.issuer - - Balances: - lowAccount has 100/USD/highAccount - lowAccount has 0/USD/lowAccount on the line - - highAccount has 0/USD/lowAccount - highAccount has -100/USD/highAccount on the line - - - * */ - - public RippleState() { - super(LedgerEntryType.RippleState); - } - - public UInt32 highQualityIn() {return get(UInt32.HighQualityIn);} - public UInt32 highQualityOut() {return get(UInt32.HighQualityOut);} - public UInt32 lowQualityIn() {return get(UInt32.LowQualityIn);} - public UInt32 lowQualityOut() {return get(UInt32.LowQualityOut);} - public UInt64 lowNode() {return get(UInt64.LowNode);} - public UInt64 highNode() {return get(UInt64.HighNode);} - public Amount balance() {return get(Amount.Balance);} - public Amount lowLimit() {return get(Amount.LowLimit);} - public Amount highLimit() {return get(Amount.HighLimit);} - public void highQualityIn(UInt32 val) {put(Field.HighQualityIn, val);} - public void highQualityOut(UInt32 val) {put(Field.HighQualityOut, val);} - public void lowQualityIn(UInt32 val) {put(Field.LowQualityIn, val);} - public void lowQualityOut(UInt32 val) {put(Field.LowQualityOut, val);} - public void lowNode(UInt64 val) {put(Field.LowNode, val);} - public void highNode(UInt64 val) {put(Field.HighNode, val);} - public void balance(Amount val) {put(Field.Balance, val);} - public void lowLimit(Amount val) {put(Field.LowLimit, val);} - public void highLimit(Amount val) {put(Field.HighLimit, val);} - - public boolean hasHighQualityIn() {return has(UInt32.HighQualityIn);} - public boolean hasHighQualityOut() {return has(UInt32.HighQualityOut);} - public boolean hasLowQualityIn() {return has(UInt32.LowQualityIn);} - public boolean hasLowQualityOut() {return has(UInt32.LowQualityOut);} - public boolean hasLowNode() {return has(UInt64.LowNode);} - public boolean hasHighNode() {return has(UInt64.HighNode);} - - public AccountID lowAccount() { - return lowLimit().issuer(); - } - - public AccountID highAccount() { - return highLimit().issuer(); - } - - public List sortedAccounts() { - return Arrays.asList(lowAccount(), highAccount()); - } - - public AmountField limitFieldFor(AccountID source) { - if (lowAccount().equals(source)) { - return Amount.LowLimit; - } - if (highAccount().equals(source)) { - return Amount.HighLimit; - } else { - return null; - } - } - - public boolean isFor(AccountID source) { - return lowAccount().equals(source) || highAccount().equals(source); - } - - public boolean isFor(Issue issue) { - return isFor(issue.issuer()) && balance().currency().equals(issue.currency()); - } - - // TODO, can optimize this - public boolean isFor(AccountID s1, AccountID s2, Currency currency) { - return currency.equals(balance().currency()) && isFor(s1) && isFor(s2); - } - - public Currency currency() { - return balance().currency(); - } - - private Amount issuedBy(boolean hi) { - Amount balance; - - if (hi) { - balance = balance().newIssuer(highAccount()); - } else { - balance = balance().negate().newIssuer(lowAccount()); - } - - if (!balance.isPositive()) { - balance = balance.issue().amount(0); - } - return balance; - } - - public Amount issuedByHigh() { - return issuedBy(true); - } - public Amount issuedByLow() { - return issuedBy(false); - } - - public Amount issuedTo(AccountID accountID) { - return issuedBy(isLowAccount(accountID)); - } - - @Deprecated() // "not deprecated but needs fixing" - public boolean authorizedBy(AccountID account) { - UInt32 flags = flags(); - return flags == null || flags.testBit(isHighAccount(account) ? LedgerFlag.HighAuth : LedgerFlag.LowAuth); - } - - private boolean isBitSet(int flags, int flag) { - return (flags & flag) != 0; - } - - private boolean isHighAccount(AccountID account) { - return highAccount().equals(account); - } - private boolean isLowAccount(AccountID account) { - return lowAccount().equals(account); - } - - - public Hash256 lowNodeOwnerDirectory() { - Hash256 ownerDir = Index.ownerDirectory(lowAccount()); - return Index.directoryNode(ownerDir, lowNode()); - } - public Hash256 highNodeOwnerDirectory() { - Hash256 ownerDir = Index.ownerDirectory(highAccount()); - return Index.directoryNode(ownerDir, highNode()); - } - - public Hash256[] directoryIndexes() { - return new Hash256[]{lowNodeOwnerDirectory(), highNodeOwnerDirectory()}; - } - - @Override - public void setDefaults() { - super.setDefaults(); - - if (lowNode() == null) { - lowNode(UInt64.ZERO); - } - if (highNode() == null) { - highNode(UInt64.ZERO); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java deleted file mode 100644 index 68af847605..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/SignerList.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.STArray; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class SignerList extends IndexedLedgerEntry { - public SignerList() { - super(LedgerEntryType.SignerList); - } - - @Override - public void setDefaults() { - super.setDefaults(); - if (!has(Field.SignerListID)) { - put(UInt32.SignerListID, UInt32.ZERO); - } - } - - public STArray signerEntries() {return get(STArray.SignerEntries);} - public UInt32 signerListID() {return get(UInt32.SignerListID);} - public UInt32 signerQuorum() {return get(UInt32.SignerQuorum);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - public void signerEntries(STArray val) { put(STArray.SignerEntries, val);} - public void signerListID(UInt32 val) { put(UInt32.SignerListID, val);} - public void signerQuorum(UInt32 val) { put(UInt32.SignerQuorum, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java b/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java deleted file mode 100644 index 5d48e3f462..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/sle/entries/Ticket.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ripple.core.types.known.sle.entries; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.LedgerEntryType; - -public class Ticket extends IndexedLedgerEntry { - public Ticket() { - super(LedgerEntryType.Ticket); - } - - public AccountID account() {return get(AccountID.Account);} - public AccountID target() {return get(AccountID.Target);} - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt32 sequence() {return get(UInt32.Sequence);} - public UInt64 ownerNode() {return get(UInt64.OwnerNode);} - - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void ownerNode(UInt64 val) { put(UInt64.OwnerNode, val);} - public void sequence(UInt32 val) { put(UInt32.Sequence, val);} - public void target(AccountID val) { put(AccountID.Target, val);} - - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasTarget() {return has(AccountID.Target);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java deleted file mode 100644 index 8f174968aa..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/Transaction.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.ripple.core.types.known.tx; - -import com.ripple.core.coretypes.*; -import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.uint.UInt16; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.enums.TransactionFlag; -import com.ripple.core.fields.Field; -import com.ripple.core.formats.TxFormat; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.signed.SignedTransaction; -import com.ripple.crypto.keys.IVerifyingKey; -import com.ripple.utils.HashUtils; - -public class Transaction extends STObject { - public static final boolean CANONICAL_FLAG_DEPLOYED = true; - public static final UInt32 CANONICAL_SIGNATURE = new UInt32(TransactionFlag.FullyCanonicalSig); - - public Transaction(TransactionType type) { - setFormat(TxFormat.formats.get(type)); - put(Field.TransactionType, type); - } - - public SignedTransaction prepare(byte[] pubKeyBytes) { - SignedTransaction tx = SignedTransaction.fromTx(this); - tx.prepare(pubKeyBytes); - return tx; - } - - public TransactionType transactionType() { - return transactionType(this); - } - - public Hash256 signingHash() { - return signingHash(HashPrefix.txSign); - } - - public byte[] signingData() { - return signingData(HashPrefix.txSign); - } - - public boolean verifySignature(AccountID key) { - Blob pubKey = signingPubKey(); - return IVerifyingKey.from(pubKey.toBytes()) - .verify(signingData(), - txnSignature().toBytes()) && - signingKey().equals(key); - } - - public boolean verifyMasterKeySignature() { - return verifySignature(account()); - } - - public void setCanonicalSignatureFlag() { - UInt32 flags = get(UInt32.Flags); - if (flags == null) { - flags = CANONICAL_SIGNATURE; - } else { - flags = flags.or(CANONICAL_SIGNATURE); - } - put(UInt32.Flags, flags); - } - - public UInt32 flags() {return get(UInt32.Flags);} - public UInt32 sourceTag() {return get(UInt32.SourceTag);} - public UInt32 sequence() {return get(UInt32.Sequence);} - public UInt32 lastLedgerSequence() {return get(UInt32.LastLedgerSequence);} - public UInt32 operationLimit() {return get(UInt32.OperationLimit);} - public Hash256 previousTxnID() {return get(Hash256.PreviousTxnID);} - public Hash256 accountTxnID() {return get(Hash256.AccountTxnID);} - public Amount fee() {return get(Amount.Fee);} - public Blob signingPubKey() {return get(Blob.SigningPubKey);} - public Blob txnSignature() {return get(Blob.TxnSignature);} - public AccountID account() {return get(AccountID.Account);} - - public void transactionType(UInt16 val) {put(Field.TransactionType, val);} - public void flags(UInt32 val) {put(Field.Flags, val);} - public void sourceTag(UInt32 val) {put(Field.SourceTag, val);} - public void sequence(UInt32 val) {put(Field.Sequence, val);} - public void lastLedgerSequence(UInt32 val) {put(Field.LastLedgerSequence, val);} - public void operationLimit(UInt32 val) {put(Field.OperationLimit, val);} - public void previousTxnID(Hash256 val) {put(Field.PreviousTxnID, val);} - public void accountTxnID(Hash256 val) {put(Field.AccountTxnID, val);} - public void fee(Amount val) {put(Field.Fee, val);} - public void signingPubKey(Blob val) {put(Field.SigningPubKey, val);} - public void txnSignature(Blob val) {put(Field.TxnSignature, val);} - public void account(AccountID val) {put(Field.Account, val);} - - public boolean hasFlags() {return has(UInt32.Flags);} - public boolean hasSourceTag() {return has(UInt32.SourceTag);} - public boolean hasLastLedgerSequence() {return has(UInt32.LastLedgerSequence);} - public boolean hasOperationLimit() {return has(UInt32.OperationLimit);} - public boolean hasPreviousTxnID() {return has(Hash256.PreviousTxnID);} - public boolean hasAccountTxnID() {return has(Hash256.AccountTxnID);} - public boolean hasTxnSignature() {return has(Blob.TxnSignature);} - public boolean hasSigners() {return has(STArray.Signers);} - public boolean hasMemos() {return has(STArray.Memos);} - - public Hash256 hash() { - return get(Hash256.hash); - } - - public Hash256 createHash() { - HalfSha512 id = HalfSha512.prefixed256(HashPrefix.transactionID); - toBytesSink(id); - return id.finish(); - } - - public AccountID signingKey() { - // May be a regular Key - byte[] pubKey = HashUtils.SHA256_RIPEMD160(signingPubKey().toBytes()); - return AccountID.fromBytes(pubKey); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java deleted file mode 100644 index 9c399b73a0..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/AffectedNode.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.ripple.core.types.known.tx.result; - -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt16; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.SerializedType; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.LedgerEntry; - -// TODO: fix up this nonsense -public class AffectedNode extends STObject { - public final Field field; - public final STObject nested; - - public AffectedNode(STObject source) { - fields = source.getFields(); - field = getField(); - nested = nestedObject(); - } - - public boolean isOffer() { - return ledgerEntryType() == LedgerEntryType.Offer; - } - - public boolean isAccountRoot() { - return ledgerEntryType() == LedgerEntryType.AccountRoot; - } - - public boolean isRippleState() { - return ledgerEntryType() == LedgerEntryType.RippleState; - } - - public boolean isDirectoryNode() { - return ledgerEntryType() == LedgerEntryType.DirectoryNode; - } - - public boolean wasPreviousNode() { - return isDeletedNode() || isModifiedNode(); - } - - public boolean isFinalNode() { - return true; - } - - public boolean isCreatedNode() { - return field == Field.CreatedNode; - } - - public boolean isDeletedNode() { - return field == Field.DeletedNode; - } - - public boolean isModifiedNode() { - return field == Field.ModifiedNode; - } - - public Field getField() { -// return iterator().next(); - return fields.firstKey(); - } - - public Hash256 ledgerIndex() { - return nested.get(Hash256.LedgerIndex); - } - - public LedgerEntryType ledgerEntryType() { - return ledgerEntryType(nested); - } - - private STObject nestedObject() { - return (STObject) get(getField()); - } - - /** - * @return - LedgerEntry before the transaction (or after in the case of - * a CreatedNode) - */ - public LedgerEntry nodeAsPrevious() { - return (LedgerEntry) rebuildFromMeta(true); - } - - public LedgerEntry nodeAsFinal() { - return (LedgerEntry) rebuildFromMeta(false); - } - - private STObject rebuildFromMeta(boolean asPrevious) { - boolean created = isCreatedNode(); - STObject mixed = new STObject(); - - // The first object has only a single key - Field wrapperField = created ? Field.CreatedNode : - isDeletedNode() ? Field.DeletedNode : - Field.ModifiedNode; - - STObject wrapped = (STObject) get(wrapperField); - - Field finalFields = created ? Field.NewFields : - Field.FinalFields; - - // You may get some AccountRoot objects like this - if (!wrapped.has(finalFields)) { - STObject source = new STObject(wrapped.getFields()); - source.put(Hash256.index, wrapped.get(Hash256.LedgerIndex)); - source.remove(Field.LedgerIndex); - return STObject.formatted(source); - } - - // Get all the final fields - STObject finals = (STObject) wrapped.get(finalFields); - for (Field field : finals) { - mixed.put(field, finals.get(field)); - } - - // Then layer over the previous fields if desired as previous - // DirectoryNode LedgerEntryType won't have `PreviousFields` - if (asPrevious && wrapped.has(Field.PreviousFields)) { - STObject previous = wrapped.get(STObject.PreviousFields); - for (Field field : previous) { - mixed.put(field, previous.get(field)); - } - } - - // Keep the inner most fields - for (Field field : wrapped) { - switch (field) { - case NewFields: - case PreviousFields: - case FinalFields: - continue; - default: - SerializedType value = wrapped.get(field); - if (field == Field.LedgerIndex) { - field = Field.index; - } - mixed.put(field, value); - - } - } - return STObject.formatted(mixed); - } - - public static boolean isAffectedNode(STObject source) { - return (source.size() == 1 && ( - source.has(DeletedNode) || - source.has(CreatedNode) || - source.has(ModifiedNode))); - } - - public boolean removedField(Field field) { - return nested.has(Field.PreviousFields) && - nested.get(STObject.PreviousFields).has(field) && - nested.has(Field.FinalFields) && - !nested.get(STObject.FinalFields).has(field); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java deleted file mode 100644 index c25183436a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionMeta.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ripple.core.types.known.tx.result; - -import com.ripple.core.coretypes.STArray; -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.serialized.enums.EngineResult; -import com.ripple.core.types.known.sle.LedgerEntry; - -import java.util.Iterator; - -public class TransactionMeta extends STObject { - public static boolean isTransactionMeta(STObject source) { - return source.has(UInt8.TransactionResult) && - source.has(STArray.AffectedNodes); - } - - public EngineResult engineResult() { - return engineResult(this); - } - - public Iterable affectedNodes() { - STArray nodes = get(STArray.AffectedNodes); - final Iterator iterator = nodes.iterator(); - return () -> iterateAffectedNodes(iterator); - } - - private static Iterator iterateAffectedNodes(final Iterator iterator) { - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public AffectedNode next() { - return (AffectedNode) iterator.next(); - } - - @Override - public void remove() { - iterator.remove(); - } - }; - } - - public UInt32 transactionIndex() { - return get(UInt32.TransactionIndex); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java deleted file mode 100644 index 2e4467bf14..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/result/TransactionResult.java +++ /dev/null @@ -1,299 +0,0 @@ -package com.ripple.core.types.known.tx.result; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.STArray; -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.EngineResult; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.sle.entries.AccountRoot; -import com.ripple.core.types.known.tx.Transaction; -import com.ripple.encodings.common.B16; -import org.json.JSONObject; - -import java.util.Map; -import java.util.TreeMap; - -public class TransactionResult implements Comparable { - // The json formatting of transaction results is a MESS - public enum Source { - request_tx_result, - request_account_tx, - request_account_tx_binary, - request_tx_binary, - ledger_transactions_expanded_with_ledger_index_injected, - transaction_subscription_notification - } - - public EngineResult engineResult; - public UInt32 ledgerIndex; - public Hash256 hash; - - // TODO: in practice this class is GENERALLY only for validated results. - // NOT strictly true as you can get results from closed but not validated - // ledgers! Though you would want to beyond testing ... - public boolean validated; - - public TransactionResult(long ledgerIndex, Hash256 hash, Transaction txn, TransactionMeta meta) { - this.ledgerIndex = new UInt32(ledgerIndex); - this.hash = hash; - this.txn = txn; - this.meta = meta; - this.engineResult = meta.engineResult(); - this.validated = true; - } - - public Transaction txn; - public TransactionMeta meta; - - public TransactionType transactionType() { - return txn.transactionType(); - } - - public AccountID createdAccount() { - AccountID destination = null; - Hash256 destinationIndex = null; - - if (transactionType() == TransactionType.Payment && meta.has(Field.AffectedNodes)) { - STArray affected = meta.get(STArray.AffectedNodes); - for (STObject node : affected) { - if (node.has(STObject.CreatedNode)) { - STObject created = node.get(STObject.CreatedNode); - if (STObject.ledgerEntryType(created) == LedgerEntryType.AccountRoot) { - if (destination == null) { - destination = txn.get(AccountID.Destination); - destinationIndex = Index.accountRoot(destination); - } - if (destinationIndex.equals(created.get(Hash256.LedgerIndex))) { - return destination; - } - } - } - } - } - return null; - } - - public Map modifiedRoots() { - TreeMap accounts = null; - - if (meta.has(Field.AffectedNodes)) { - accounts = new TreeMap<>(); - for (AffectedNode fields : meta.affectedNodes()) { - if (fields.isModifiedNode() && fields.isAccountRoot()) { - AccountRoot root = (AccountRoot) fields.nodeAsFinal(); - //noinspection StatementWithEmptyBody - if (root.account() != null) { - accounts.put(root.account(), root); - } else { - // TODO: Remember why these modified nodes have no - // FinalFields or NewFields - /* - {"ModifiedNode": { - "LedgerIndex": "2C6F7594FB7471F4983C2BC691AAC2F25F8DB88D455985B4181E053D7AB23006", - "PreviousTxnLgrSeq": 35561097, - "LedgerEntryType": "AccountRoot", - "index": "2C6F7594FB7471F4983C2BC691AAC2F25F8DB88D455985B4181E053D7AB23006", - "PreviousTxnID": "67EE84E892FBEDF5FD52D511FF1E833870A2B8104CA5FF9BA89867A528A5D3ED" - }} - * */ - } - } - } - } - return accounts; - } - - public AccountID initiatingAccount() { - return txn.get(AccountID.Account); - } - - public int compareTo(TransactionResult o2) { - TransactionResult o1 = this; - int i = o1.ledgerIndex.compareTo(o2.ledgerIndex); - if (i != 0) { - return i; - } else { - return o1.meta.transactionIndex() - .compareTo(o2.meta.transactionIndex()); - } - } - - public static TransactionResult fromJSON(ObjectNode json) { - // TODO: obviously ... - return fromJSON(new JSONObject(json.toString())); - } - - public static TransactionResult fromJSON(JSONObject json) { - boolean binary; - - String metaKey = json.has("meta") ? "meta" : "metaData"; - - String txKey = json.has("transaction") ? "transaction" : - json.has("tx") ? "tx" : - json.has("tx_blob") ? "tx_blob" : null; - - if (txKey == null && !json.has("TransactionType")) { - throw new IllegalArgumentException("This json isn't a transaction " + json); - } - - binary = txKey != null && json.get(txKey) instanceof String; - - Transaction txn; - if (txKey == null) { - // This should parse the `hash` field - txn = (Transaction) STObject.fromJSONObject(json); - } else { - txn = (Transaction) parseObject(json, txKey, binary); - if (json.has("hash")) { - txn.put(Hash256.hash, Hash256.fromHex(json.getString("hash"))); - } else if (binary) { - byte[] decode = B16.decode(json.getString(txKey)); - txn.put(Hash256.hash, Index.transactionID(decode)); - } - } - - TransactionMeta meta = (TransactionMeta) parseObject(json, metaKey, binary); - long ledger_index = json.optLong("ledger_index", 0); - if (ledger_index == 0 && !binary) { - ledger_index = json.getJSONObject(txKey).getLong("ledger_index"); - } - - TransactionResult tr = new TransactionResult(ledger_index, txn.get(Hash256.hash), txn, meta); -// if (json.has("ledger_hash")) { -// tr.ledgerHash = Hash256.fromHex(json.getString("ledger_hash")); -// } - return tr; - } - - private static STObject parseObject(JSONObject json, String key, boolean binary) { - if (binary) { - return STObject.fromHex(json.getString(key)); - } else { - JSONObject tx_json = json.getJSONObject(key); - return STObject.fromJSONObject(tx_json); - } - } - - public TransactionResult(JSONObject json, Source resultMessageSource) { - if (resultMessageSource == Source.transaction_subscription_notification) { - - engineResult = EngineResult.valueOf(json.getString("engine_result")); - validated = json.getBoolean("validated"); -// ledgerHash = Hash256.fromHex(json.getString("ledger_hash")); - ledgerIndex = new UInt32(json.getLong("ledger_index")); - - if (json.has("transaction")) { - txn = (Transaction) STObject.fromJSONObject(json.getJSONObject("transaction")); - hash = txn.get(Hash256.hash); - } - - if (json.has("meta")) { - meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); - } - } - else if (resultMessageSource == Source.ledger_transactions_expanded_with_ledger_index_injected) { - validated = true; - meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("metaData")); - txn = (Transaction) STObject.fromJSONObject(json); - hash = txn.get(Hash256.hash); - engineResult = meta.engineResult(); - ledgerIndex = new UInt32(json.getLong("ledger_index")); - - } else if (resultMessageSource == Source.request_tx_result) { - validated = json.optBoolean("validated", false); - if (validated && !json.has("meta")) { - throw new IllegalStateException("It's validated, why doesn't it have meta??"); - } - if (validated) { - meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); - engineResult = meta.engineResult(); - txn = (Transaction) STObject.fromJSONObject(json); - hash = txn.get(Hash256.hash); - ledgerIndex = new UInt32(json.getLong("ledger_index")); - - } - } else if (resultMessageSource == Source.request_account_tx) { - validated = json.optBoolean("validated", false); - if (validated && !json.has("meta")) { - throw new IllegalStateException("It's validated, why doesn't it have meta??"); - } - if (validated) { - JSONObject tx = json.getJSONObject("tx"); - meta = (TransactionMeta) STObject.fromJSONObject(json.getJSONObject("meta")); - engineResult = meta.engineResult(); - this.txn = (Transaction) STObject.fromJSONObject(tx); - hash = this.txn.get(Hash256.hash); - ledgerIndex = new UInt32(tx.getLong("ledger_index")); - } - } else if (resultMessageSource == Source.request_account_tx_binary || resultMessageSource == Source.request_tx_binary) { - validated = json.optBoolean("validated", false); - if (validated && !json.has("meta")) { - throw new IllegalStateException("It's validated, why doesn't it have meta??"); - } - if (validated) { - /* - { - "ledger_index": 3378767, - "meta": "201 ...", - "tx_blob": "120 ...", - "validated": true - }, - */ - boolean account_tx = resultMessageSource == Source.request_account_tx_binary; - - String tx = json.getString(account_tx ? "tx_blob" : "tx"); - byte[] decodedTx = B16.decode(tx); - meta = (TransactionMeta) STObject.fromHex(json.getString("meta")); - this.txn = (Transaction) STObject.fromBytes(decodedTx); - - if (account_tx) { - hash = Index.transactionID(decodedTx); - } else { - hash = Hash256.fromHex(json.getString("hash")); - } - this.txn.put(Field.hash, hash); - - engineResult = meta.engineResult(); - ledgerIndex = new UInt32(json.getLong("ledger_index")); - } - } - } - - @Override - public String toString() { - JSONObject object = toJSON(); - return object.toString(); - } - - public JSONObject toJSON() { - JSONObject o = new JSONObject(); - o.put("tx", txn.toJSON()); - o.put("meta", meta.toJSON()); - o.put("ledger_index", ledgerIndex); - o.put("hash", hash.toHex()); - return o; - } - - public TransactionResult copy() { - TransactionMeta metaCopy = (TransactionMeta) STObject.fromBytes(meta.toBytes()); - Transaction txnCopy = (Transaction) STObject.fromBytes(txn.toBytes()); - return new TransactionResult(ledgerIndex.longValue(), hash, txnCopy, metaCopy); - } - - public JSONObject toJSONBinary() { - JSONObject o = new JSONObject(); - - o.put("hash", hash.toHex()); - o.put("meta", meta.toHex()); - o.put("tx", txn.toHex()); - o.put("ledger_index", ledgerIndex); - - return o; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java deleted file mode 100644 index 0e8a1c9672..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/AccountSet.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.hash.Hash128; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class AccountSet extends Transaction{ - public AccountSet() { - super(TransactionType.AccountSet); - } - public UInt32 transferRate() {return get(UInt32.TransferRate);} - public UInt32 walletSize() {return get(UInt32.WalletSize);} - public UInt32 setFlag() {return get(UInt32.SetFlag);} - public UInt32 clearFlag() {return get(UInt32.ClearFlag);} - public Hash128 emailHash() {return get(Hash128.EmailHash);} - public Hash256 walletLocator() {return get(Hash256.WalletLocator);} - public Blob messageKey() {return get(Blob.MessageKey);} - public Blob domain() {return get(Blob.Domain);} - public UInt8 tickSize() {return get(UInt8.TickSize);} - - public void transferRate(UInt32 val) {put(Field.TransferRate, val);} - public void walletSize(UInt32 val) {put(Field.WalletSize, val);} - public void setFlag(UInt32 val) {put(Field.SetFlag, val);} - public void clearFlag(UInt32 val) {put(Field.ClearFlag, val);} - public void emailHash(Hash128 val) {put(Field.EmailHash, val);} - public void walletLocator(Hash256 val) {put(Field.WalletLocator, val);} - public void messageKey(Blob val) {put(Field.MessageKey, val);} - public void domain(Blob val) {put(Field.Domain, val);} - public void tickSize(UInt8 val) { put(UInt8.TickSize, val);} - - public boolean hasTransferRate() {return has(UInt32.TransferRate);} - public boolean hasWalletSize() {return has(UInt32.WalletSize);} - public boolean hasSetFlag() {return has(UInt32.SetFlag);} - public boolean hasClearFlag() {return has(UInt32.ClearFlag);} - public boolean hasEmailHash() {return has(Hash128.EmailHash);} - public boolean hasWalletLocator() {return has(Hash256.WalletLocator);} - public boolean hasMessageKey() {return has(Blob.MessageKey);} - public boolean hasDomain() {return has(Blob.Domain);} - public boolean hasTickSize() {return has(UInt8.TickSize);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java deleted file mode 100644 index f5b961f514..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCancel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class CheckCancel extends Transaction { - public CheckCancel() { - super(TransactionType.CheckCancel); - } - - public Hash256 checkID() {return get(Hash256.CheckID);} - public void checkID(Hash256 val) { put(Hash256.CheckID, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java deleted file mode 100644 index 8eba2458e9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCash.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class CheckCash extends Transaction { - public CheckCash() { - super(TransactionType.CheckCash); - } - - public boolean hasAmount() {return has(Amount.Amount);} - public boolean hasDeliverMin() {return has(Amount.DeliverMin);} - - public Hash256 checkID() {return get(Hash256.CheckID);} - public Amount amount() {return get(Amount.Amount);} - public Amount deliverMin() {return get(Amount.DeliverMin);} - - public void checkID(Hash256 val) { put(Hash256.CheckID, val);} - public void amount(Amount val) { put(Amount.Amount, val);} - public void deliverMin(Amount val) { put(Amount.DeliverMin, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java deleted file mode 100644 index b8e75a9b0f..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/CheckCreate.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class CheckCreate extends Transaction { - public CheckCreate() { - super(TransactionType.CheckCreate); - } - - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} - - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void invoiceID(Hash256 val) { put(Hash256.InvoiceID, val);} - public void sendMax(Amount val) { put(Amount.SendMax, val);} - public void destination(AccountID val) { put(AccountID.Destination, val); } - - public AccountID destination() {return get(AccountID.Destination);} - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public Hash256 invoiceID() {return get(Hash256.InvoiceID);} - public Amount sendMax() {return get(Amount.SendMax);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java deleted file mode 100644 index 68f08cde32..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/DepositPreauth.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class DepositPreauth extends Transaction { - public DepositPreauth() { - super(TransactionType.DepositPreauth); - } - public boolean hasAuthorize() {return has(AccountID.Authorize);} - public AccountID authorize() {return get(AccountID.Authorize);} - public void authorize(AccountID val) { put(AccountID.Authorize, val);} - - public boolean hasUnauthorize() {return has(AccountID.Unauthorize);} - public AccountID unauthorize() {return get(AccountID.Unauthorize);} - public void unauthorize(AccountID val) { put(AccountID.Unauthorize, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java deleted file mode 100644 index ab435bacda..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCancel.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class EscrowCancel extends Transaction { - public EscrowCancel() { - super(TransactionType.EscrowCancel); - } - - public UInt32 offerSequence() {return get(UInt32.OfferSequence);} - public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} - public AccountID owner() {return get(AccountID.Owner);} - public void owner(AccountID val) { put(AccountID.Owner, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java deleted file mode 100644 index 3587a6c191..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowCreate.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class EscrowCreate extends Transaction { - public EscrowCreate() { - super(TransactionType.EscrowCreate); - } - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} - public boolean hasFinishAfter() {return has(UInt32.FinishAfter);} - public boolean hasCondition() {return has(Blob.Condition);} - - public Amount amount() {return get(Amount.Amount);} - public AccountID destination() {return get(AccountID.Destination);} - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} - public UInt32 finishAfter() {return get(UInt32.FinishAfter);} - public Blob condition() {return get(Blob.Condition);} - - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} - public void finishAfter(UInt32 val) { put(UInt32.FinishAfter, val);} - public void amount(Amount val) { put(Amount.Amount, val);} - public void condition(Blob val) { put(Blob.Condition, val);} - public void destination(AccountID val) { put(AccountID.Destination, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java deleted file mode 100644 index 7b552e768d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/EscrowFinish.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class EscrowFinish extends Transaction { - public EscrowFinish() { - super(TransactionType.EscrowFinish); - } - - public boolean hasFulfillment() {return has(Blob.Fulfillment);} - public boolean hasCondition() {return has(Blob.Condition);} - - public UInt32 offerSequence() {return get(UInt32.OfferSequence);} - public Blob fulfillment() {return get(Blob.Fulfillment);} - public Blob condition() {return get(Blob.Condition);} - public AccountID owner() {return get(AccountID.Owner);} - - public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} - public void fulfillment(Blob val) { put(Blob.Fulfillment, val);} - public void condition(Blob val) { put(Blob.Condition, val);} - public void owner(AccountID val) { put(AccountID.Owner, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java deleted file mode 100644 index 461d6cac09..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCancel.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class OfferCancel extends Transaction { - public OfferCancel() { - super(TransactionType.OfferCancel); - } - public UInt32 offerSequence() {return get(UInt32.OfferSequence);} - public void offerSequence(UInt32 val) { put(UInt32.OfferSequence, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java deleted file mode 100644 index dbb783479d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/OfferCreate.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class OfferCreate extends Transaction { - public OfferCreate() { - super(TransactionType.OfferCreate); - } - public UInt32 expiration() {return get(UInt32.Expiration);} - public UInt32 offerSequence() {return get(UInt32.OfferSequence);} - public Amount takerPays() {return get(Amount.TakerPays);} - public Amount takerGets() {return get(Amount.TakerGets);} - public void expiration(UInt32 val) {put(Field.Expiration, val);} - public void offerSequence(UInt32 val) {put(Field.OfferSequence, val);} - public void takerPays(Amount val) {put(Field.TakerPays, val);} - public void takerGets(Amount val) {put(Field.TakerGets, val);} - - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasOfferSequence() {return has(UInt32.OfferSequence);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java deleted file mode 100644 index 10da726d71..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/Payment.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.PathSet; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class Payment extends Transaction { - public Payment() { - super(TransactionType.Payment); - } - - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public Hash256 invoiceID() {return get(Hash256.InvoiceID);} - public Amount amount() {return get(Amount.Amount);} - public Amount sendMax() {return get(Amount.SendMax);} - public AccountID destination() {return get(AccountID.Destination);} - - public PathSet paths() {return get(PathSet.Paths);} - public Amount deliverMin() {return get(Amount.DeliverMin);} - - public void destinationTag(UInt32 val) {put(Field.DestinationTag, val);} - public void invoiceID(Hash256 val) {put(Field.InvoiceID, val);} - public void deliverMin(Amount val) { put(Amount.DeliverMin, val);} - public void amount(Amount val) {put(Field.Amount, val);} - public void sendMax(Amount val) {put(Field.SendMax, val);} - public void destination(AccountID val) {put(Field.Destination, val);} - public void paths(PathSet val) {put(Field.Paths, val);} - - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasInvoiceID() {return has(Hash256.InvoiceID);} - public boolean hasSendMax() {return has(Amount.SendMax);} - public boolean hasDeliverMin() {return has(Amount.DeliverMin);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java deleted file mode 100644 index 8632dbd8b3..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelClaim.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class PaymentChannelClaim extends Transaction { - public PaymentChannelClaim() { - super(TransactionType.PaymentChannelClaim); - } - - public boolean hasAmount() {return has(Amount.Amount);} - public boolean hasBalance() {return has(Amount.Balance);} - public boolean hasPublicKey() {return has(Blob.PublicKey);} - public boolean hasSignature() {return has(Blob.Signature);} - - public void channel(Hash256 val) { put(Hash256.Channel, val);} - public void amount(Amount val) { put(Amount.Amount, val);} - public void balance(Amount val) { put(Amount.Balance, val);} - public void publicKey(Blob val) { put(Blob.PublicKey, val);} - public void signature(Blob val) { put(Blob.Signature, val);} - - public Hash256 channel() {return get(Hash256.Channel);} - public Amount amount() {return get(Amount.Amount);} - public Amount balance() {return get(Amount.Balance);} - public Blob publicKey() {return get(Blob.PublicKey);} - public Blob signature() {return get(Blob.Signature);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java deleted file mode 100644 index 2475c637e5..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelCreate.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.Blob; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class PaymentChannelCreate extends Transaction { - public PaymentChannelCreate() { - super(TransactionType.PaymentChannelCreate); - } - - public boolean hasDestinationTag() {return has(UInt32.DestinationTag);} - public boolean hasCancelAfter() {return has(UInt32.CancelAfter);} - - public void destinationTag(UInt32 val) { put(UInt32.DestinationTag, val);} - public void cancelAfter(UInt32 val) { put(UInt32.CancelAfter, val);} - public void settleDelay(UInt32 val) { put(UInt32.SettleDelay, val);} - public void amount(Amount val) { put(Amount.Amount, val);} - public void publicKey(Blob val) { put(Blob.PublicKey, val);} - public void destination(AccountID val) { put(AccountID.Destination, val);} - - public UInt32 destinationTag() {return get(UInt32.DestinationTag);} - public UInt32 cancelAfter() {return get(UInt32.CancelAfter);} - public UInt32 settleDelay() {return get(UInt32.SettleDelay);} - public Amount amount() {return get(Amount.Amount);} - public Blob publicKey() {return get(Blob.PublicKey);} - public AccountID destination() {return get(AccountID.Destination);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java deleted file mode 100644 index 85ccff90f4..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/PaymentChannelFund.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class PaymentChannelFund extends Transaction { - public PaymentChannelFund() { - super(TransactionType.PaymentChannelFund); - } - public boolean hasExpiration() {return has(UInt32.Expiration);} - - public UInt32 expiration() {return get(UInt32.Expiration);} - public Hash256 channel() {return get(Hash256.Channel);} - public Amount amount() {return get(Amount.Amount);} - - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void channel(Hash256 val) { put(Hash256.Channel, val);} - public void amount(Amount val) { put(Amount.Amount, val);} - -} - diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java deleted file mode 100644 index 5d139c75f9..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SetRegularKey.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class SetRegularKey extends Transaction { - public SetRegularKey() { - super(TransactionType.SetRegularKey); - } - public boolean hasRegularKey() {return has(AccountID.RegularKey);} - public AccountID regularKey() {return get(AccountID.RegularKey);} - public void regularKey(AccountID val) { put(AccountID.RegularKey, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java deleted file mode 100644 index 830381f8ff..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/SignerListSet.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.STArray; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class SignerListSet extends Transaction { - public SignerListSet() { - super(TransactionType.SignerListSet); - } - public boolean hasSignerEntries() {return has(STArray.SignerEntries);} - - public UInt32 signerQuorum() {return get(UInt32.SignerQuorum);} - public STArray signerEntries() {return get(STArray.SignerEntries);} - - public void signerQuorum(UInt32 val) { put(UInt32.SignerQuorum, val);} - public void signerEntries(STArray val) { put(STArray.SignerEntries, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java deleted file mode 100644 index a75f525e52..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCancel.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class TicketCancel extends Transaction { - public TicketCancel() { - super(TransactionType.TicketCancel); - } - public Hash256 ticketID() { - return get(Hash256.TicketID); - } - public void ticketID(Hash256 id) { - put(Hash256.TicketID, id); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java deleted file mode 100644 index 4e8ac5fb3f..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TicketCreate.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.AccountID; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class TicketCreate extends Transaction { - public TicketCreate() { - super(TransactionType.TicketCreate); - } - - public boolean hasExpiration() {return has(UInt32.Expiration);} - public boolean hasTarget() {return has(AccountID.Target);} - - public UInt32 expiration() {return get(UInt32.Expiration);} - public AccountID target() {return get(AccountID.Target);} - - public void expiration(UInt32 val) { put(UInt32.Expiration, val);} - public void target(AccountID val) { put(AccountID.Target, val);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java deleted file mode 100644 index ba5702c2e4..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/TrustSet.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ripple.core.types.known.tx.txns; - -import com.ripple.core.coretypes.Amount; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class TrustSet extends Transaction { - public TrustSet() { - super(TransactionType.TrustSet); - } - - public UInt32 qualityIn() {return get(UInt32.QualityIn);} - public UInt32 qualityOut() {return get(UInt32.QualityOut);} - public Amount limitAmount() {return get(Amount.LimitAmount);} - public void qualityIn(UInt32 val) {put(Field.QualityIn, val);} - public void qualityOut(UInt32 val) {put(Field.QualityOut, val);} - public void limitAmount(Amount val) {put(Field.LimitAmount, val);} - - public boolean hasQualityIn() {return has(UInt32.QualityIn);} - public boolean hasQualityOut() {return has(UInt32.QualityOut);} - public boolean hasLimitAmount() {return has(Amount.LimitAmount);} - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java deleted file mode 100644 index b65fc929e6..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/EnableAmendment.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.ripple.core.types.known.tx.txns.pseudo; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class EnableAmendment extends Transaction { - public EnableAmendment() { - super(TransactionType.EnableAmendment); - } - - public UInt32 ledgerSequence() {return get(UInt32.LedgerSequence);} - public void ledgerSequence(UInt32 val) { put(UInt32.LedgerSequence, val);} - public Hash256 amendment() {return get(Hash256.Amendment);} - public void amendment(Hash256 val) { put(Hash256.Amendment, val);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java b/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java deleted file mode 100644 index 800f13e35f..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/known/tx/txns/pseudo/SetFee.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ripple.core.types.known.tx.txns.pseudo; - -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.serialized.enums.TransactionType; -import com.ripple.core.types.known.tx.Transaction; - -public class SetFee extends Transaction { - public SetFee() { - super(TransactionType.SetFee); - } - public boolean hasLedgerSequence() {return has(UInt32.LedgerSequence);} - - public void ledgerSequence(UInt32 val) { put(UInt32.LedgerSequence, val);} - public void referenceFeeUnits(UInt32 val) { put(UInt32.ReferenceFeeUnits, val);} - public void reserveBase(UInt32 val) { put(UInt32.ReserveBase, val);} - public void reserveIncrement(UInt32 val) { put(UInt32.ReserveIncrement, val);} - public void baseFee(UInt64 val) { put(UInt64.BaseFee, val);} - - public UInt32 ledgerSequence() {return get(UInt32.LedgerSequence);} - public UInt32 referenceFeeUnits() {return get(UInt32.ReferenceFeeUnits);} - public UInt32 reserveBase() {return get(UInt32.ReserveBase);} - public UInt32 reserveIncrement() {return get(UInt32.ReserveIncrement);} - public UInt64 baseFee() {return get(UInt64.BaseFee);} -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java b/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java deleted file mode 100644 index 240b0f6da8..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/ledger/LedgerHeader.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.ripple.core.types.ledger; - -import com.ripple.core.binary.STReader; -import com.ripple.core.coretypes.RippleDate; -import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.coretypes.uint.UInt64; -import com.ripple.core.coretypes.uint.UInt8; -import com.ripple.core.serialized.BinaryParser; -import com.ripple.core.serialized.BytesSink; -import org.json.JSONObject; -import org.json.JSONWriter; - -import java.util.Date; - -public class LedgerHeader { - // Always 0x4C475200 (LWR) (Secures signed objects) - public UInt32 version = HashPrefix.ledgerMaster.uInt32(); - - public UInt32 sequence; // Ledger Sequence (0 for genesis ledger) - public UInt64 totalXRP; // - public Hash256 previousLedger; // The hash of the previous ledger (0 for genesis ledger) - public Hash256 transactionHash; // The hash of the transaction tree's root node. - public Hash256 stateHash; // The hash of the state tree's root node. - public UInt32 parentCloseTime; // The time the previous ledger closed - public UInt32 closeTime; // UTC minute ledger closed encoded as seconds since 1/1/2000 (or 0 for genesis ledger) - public UInt8 closeResolution; // The resolution (in seconds) of the close time - public UInt8 closeFlags; // Flags - - public Date closeDate; - - public static LedgerHeader fromParser(BinaryParser parser) { - return fromReader(new STReader(parser)); - } - public static LedgerHeader fromHex(String ledger_data) { - return LedgerHeader.fromParser(new BinaryParser(ledger_data)); - } - - public static LedgerHeader fromReader(STReader reader) { - LedgerHeader ledger = new LedgerHeader(); - - ledger.sequence = reader.uInt32(); - ledger.totalXRP = reader.uInt64(); - ledger.previousLedger = reader.hash256(); - ledger.transactionHash= reader.hash256(); - ledger.stateHash = reader.hash256(); - ledger.parentCloseTime = reader.uInt32(); - ledger.closeTime = reader.uInt32(); - ledger.closeResolution = reader.uInt8(); - ledger.closeFlags = reader.uInt8(); - - ledger.closeDate = RippleDate.fromSecondsSinceRippleEpoch(ledger.closeTime); - - return ledger; - } - - public void toBytesSink(BytesSink sink) { - sequence.toBytesSink(sink); - totalXRP.toBytesSink(sink); - previousLedger.toBytesSink(sink); - transactionHash.toBytesSink(sink); - stateHash.toBytesSink(sink); - parentCloseTime.toBytesSink(sink); - closeTime.toBytesSink(sink); - closeResolution.toBytesSink(sink); - closeFlags.toBytesSink(sink); - } - - public Hash256 hash() { - HalfSha512 half = HalfSha512.prefixed256(HashPrefix.ledgerMaster); - toBytesSink(half); - return half.finish(); - } - - public void toJSONWriter(JSONWriter writer) { - writer.key("ledger_index"); - writer.value(sequence.toJSON()); - writer.key("total_coins"); - writer.value(totalXRP.toString(10)); - writer.key("parent_hash"); - writer.value(previousLedger.toJSON()); - writer.key("transaction_hash"); - writer.value(transactionHash.toJSON()); - writer.key("account_hash"); - writer.value(stateHash.toJSON()); - writer.key("close_time"); - writer.value(closeTime.toJSON()); - writer.key("close_time_human"); - // TODO - writer.value(RippleDate.gmtString(RippleDate.fromSecondsSinceRippleEpoch(closeTime))); - writer.key("parent_close_time"); - writer.value(parentCloseTime.toJSON()); - writer.key("close_time_resolution"); - writer.value(closeResolution.toJSON()); - writer.key("close_flags"); - writer.value(closeFlags.toJSON()); - } - - public JSONObject toJSON() { - StringBuilder builder = new StringBuilder(); - JSONWriter jsonWriter = new JSONWriter(builder); - jsonWriter.object(); - toJSONWriter(jsonWriter); - jsonWriter.endObject(); - return new JSONObject(builder.toString()); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java deleted file mode 100644 index c6eaadd3fa..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountState.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.Vector256; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.Index; -import com.ripple.core.coretypes.uint.UInt32; -import com.ripple.core.serialized.enums.LedgerEntryType; -import com.ripple.core.types.known.sle.LedgerEntry; -import com.ripple.core.types.known.sle.LedgerHashes; -import com.ripple.core.types.known.sle.entries.DirectoryNode; -import com.ripple.core.types.known.sle.entries.OfferDirectory; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.json.JSONWriter; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; -import java.util.Iterator; - -public class AccountState extends ShaMap { - public AccountState() { - super(); - } - public AccountState(boolean isCopy, int depth) { - super(isCopy, depth); - } - - @Override - protected ShaMapInner makeInnerOfSameClass(int depth) { - return new AccountState(true, depth); - } - - private static LedgerHashes newSkipList(Hash256 skipIndex) { - LedgerHashes skip; - skip = new LedgerHashes(); - skip.put(UInt32.Flags, new UInt32(0)); - skip.hashes(new Vector256()); - skip.index(skipIndex); - return skip; - } - - public void updateSkipLists(long currentIndex, Hash256 parentHash) { - long prev = currentIndex - 1; - - if ((prev & 0xFF) == 0) { - Hash256 skipIndex = Index.ledgerHashes(prev); - LedgerHashes skip = createOrUpdateSkipList(skipIndex); - Vector256 hashes = skip.hashes(); - assert hashes.size() <= 256; - hashes.add(parentHash); - skip.put(UInt32.LastLedgerSequence, new UInt32(prev)); - } - - Hash256 skipIndex = Index.ledgerHashes(); - LedgerHashes skip = createOrUpdateSkipList(skipIndex); - Vector256 hashes = skip.hashes(); - - if (hashes.size() > 256) throw new AssertionError(); - if (hashes.size() == 256) { - hashes.remove(0); - } - - hashes.add(parentHash); - skip.put(UInt32.LastLedgerSequence, new UInt32(prev)); - } - - private LedgerHashes createOrUpdateSkipList(Hash256 skipIndex) { - PathToIndex path = pathToIndex(skipIndex); - ShaMapInner top = path.dirtyOrCopyInners(); - LedgerEntryItem item; - - if (path.hasMatchedLeaf()) { - ShaMapLeaf leaf = path.invalidatedPossiblyCopiedLeafForUpdating(); - item = (LedgerEntryItem) leaf.item; - } else { - item = new LedgerEntryItem(newSkipList(skipIndex)); - top.addLeafToTerminalInner(new ShaMapLeaf(skipIndex, item)); - } - return (LedgerHashes) item.entry; - } - - public boolean addLE(LedgerEntry entry) { - LedgerEntryItem item = new LedgerEntryItem(entry); - return addItem(entry.index(), item); - } - - public boolean updateLE(LedgerEntry entry) { - LedgerEntryItem item = new LedgerEntryItem(entry); - return updateItem(entry.index(), item); - } - - public LedgerEntry getLE(Hash256 index) { - LedgerEntryItem item = (LedgerEntryItem) getItem(index); - return item == null ? null : item.value(); - } - - public DirectoryNode getDirectoryNode(Hash256 index) { - return (DirectoryNode) getLE(index); - } - - public Iterable offerDirectories(Hash256 bookBase) { - final QualityIterator iter = qualityIterator(bookBase); - - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - boolean hasNext = iter.hasNext(); - // In case we need to skip some entries - if (hasNext && !(iter.next() instanceof OfferDirectory)) { - return this.hasNext(); - } - return hasNext; - } - - @Override - public OfferDirectory next() { - return (OfferDirectory) iter.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - public void writeEntriesArray(final JSONWriter writer) { - writer.array(); - walkEntries(entry -> writer.value(entry.toJSON())); - writer.endArray(); - } - - // Assumes shamap won't be modified during iteration, not unusual for an - // iterator. - public class QualityIterator implements Iterator { - ShaMapInner[] inners = new ShaMapInner[64]; - Hash256 base; - Hash256 end; - int[] selections = new int[64]; - int commonNibblets; - int depth; - ShaMapLeaf next; - private boolean finished = false; - - public QualityIterator(Hash256 start) { - base = start; - depth=0; - end = Index.bookEnd(start); - ShaMapInner inner = AccountState.this; - setInner(inner); - setSelected(start.nibblet(depth)); - findCommonNibblets(); - } - - private void findCommonNibblets() { - for (int i = 0; i < 64; i++) { - if (base.nibblet(i) == end.nibblet(i)) { - commonNibblets = i; - } else { - break; - } - } - } - - private void setInner(ShaMapInner inner) { - inners[depth] = inner; - } - - private void findNext() { - next = null; - - while (true) { - while (selected() > 15) { - depth--; - incrementSelection(); - } - if (depth < commonNibblets && selected() > end.nibblet(depth)) { - finished = true; - break; - } - ShaMapInner current = currentInner(); - ShaMapNode branch = current.getBranch(selected()); - if (branch == null) { - incrementSelection(); - } else if (branch.isInner()) { - depth++; - setInner(branch.asInner()); - setSelected(base.nibblet(depth)); - } else if (branch.isLeaf()) { - ShaMapLeaf leaf = branch.asLeaf(); - Hash256 leafIndex = leaf.index; - boolean leafIsOnPathToBase = depth < commonNibblets; - if ( leafIsOnPathToBase || leafIndex.compareTo(base) > 0 && - leafIndex.compareTo(end) < 0) { - next = leaf; - incrementSelection(); - } else { - finished = true; - } - break; - } - } - } - - private ShaMapInner currentInner() { - return inners[depth]; - } - private int selected() { - return selections[depth]; - } - private void setSelected(int nibblet) { - selections[depth] = nibblet; - } - private void incrementSelection() { - selections[depth]++; - } - - @Override - public boolean hasNext() { - findNext(); - return !finished && next != null; - } - @Override - public LedgerEntry next() { - // Just assume hasNext has been called - LedgerEntryItem item = (LedgerEntryItem) next.item; - return item.entry; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - public QualityIterator qualityIterator(final Hash256 bookBase) { - return new QualityIterator(bookBase); - } - - public Iterable directoryIterator(OfferDirectory forQuality) { - // TODO: create an actual iterator - Vector256 indexes = new Vector256(); - OfferDirectory cursor = forQuality; - - while (cursor != null) { - indexes.addAll(cursor.indexes()); - if (cursor.hasNextIndex()) { - LedgerEntry le = getLE(cursor.nextIndex()); - if (le instanceof OfferDirectory) { - cursor = (OfferDirectory) le; - } - else { - break; - } - } - else { - break; - } - } - return indexes; - } - - public void walkEntries(final LedgerEntryVisitor walker) { - walkLeaves(leaf -> { - LedgerEntryItem item = (LedgerEntryItem) leaf.item; - walker.onEntry(item.entry); - }); - } - - // TODO - public Hash256 getNextIndex(Hash256 nextIndex, Hash256 bookEnd) { - return null; - } - - @Override - public AccountState copy() { - return (AccountState) super.copy(); - } - - public static AccountState loadFromLedgerDump(String filePath) { - try { - FileReader reader = new FileReader(filePath); - return loadFromLedgerDump(reader); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } - - public static AccountState loadFromLedgerDump(Reader reader) { - try { - JsonFactory jsonFactory = new JsonFactory(); - JsonParser parser = jsonFactory.createParser(reader); - JsonToken jsonToken = parser.nextToken(); - if (jsonToken != JsonToken.START_OBJECT) { - throw new AssertionError(); - } - - String accountState = "accountState"; - - // TODO: - while (parser.nextToken() != null) { - String currentName = parser.getCurrentName(); - if (currentName.equals(accountState)) { - break; - } - } - - if (!parser.getCurrentName().equals("accountState")) { - throw new IllegalStateException("No `accountState` field found!"); - } - - AccountState state = new AccountState(); - ObjectMapper mapper = new ObjectMapper(); - if (parser.nextToken() != JsonToken.START_ARRAY) { - throw new AssertionError(); - } - - while (parser.nextToken() != JsonToken.END_ARRAY) { - TreeNode treeNode = mapper.readTree(parser); - state.addLE((LedgerEntry) STObject.fromJacksonObject((ObjectNode) treeNode)); - } - return state; - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java deleted file mode 100644 index 1b43203db7..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/AccountStateBuilder.java +++ /dev/null @@ -1,320 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.fields.Field; -import com.ripple.core.types.known.sle.LedgerEntry; -import com.ripple.core.types.known.sle.ThreadedLedgerEntry; -import com.ripple.core.types.known.sle.entries.*; -import com.ripple.core.types.known.tx.result.AffectedNode; -import com.ripple.core.types.known.tx.result.TransactionResult; - -import java.util.*; - -public class AccountStateBuilder { - private AccountState state; - private AccountState previousState = null; - private long targetLedgerIndex; - public long nextTransactionIndex = 0; - private Hash256 targetAccountHash; - public long totalTransactions = 0; - - private TreeSet directoriesModifiedMoreThanOnceByTransaction = new TreeSet<>(); - private TreeSet directoriesModifiedByTransaction = new TreeSet<>(); - public TreeSet ledgerModifiedEntries = new TreeSet<>(); - public TreeSet ledgerDeletedEntries = new TreeSet<>(); - - public boolean sortedDirectories = true; - - public void resetModified() { - ledgerModifiedEntries.clear(); - ledgerDeletedEntries.clear(); - directoriesModifiedMoreThanOnceByTransaction.clear(); - } - - public AccountStateBuilder(AccountState state, long targetLedgerIndex) { - this.state = state; - setStateCheckPoint(); - this.targetLedgerIndex = targetLedgerIndex; - } - - public void onLedgerClose(long ledgerIndex, Hash256 accountHash, Hash256 parentHash) { - state.updateSkipLists(ledgerIndex, parentHash); - targetLedgerIndex = ledgerIndex; - targetAccountHash = accountHash; - nextTransactionIndex = 0; - } - - public void setStateCheckPoint() { - previousState = state.copy(); - } - - public void onTransaction(TransactionResult tr) { - System.out.println("adding tx: " + tr.hash); - if (tr.meta.transactionIndex().longValue() != nextTransactionIndex) throw new AssertionError(); - if (tr.ledgerIndex.longValue() != targetLedgerIndex + 1) throw new AssertionError(String.format("%d != %d", tr.ledgerIndex.longValue(), targetLedgerIndex + 1)); - nextTransactionIndex++; - totalTransactions++; - directoriesModifiedByTransaction = new TreeSet<>(); - - for (AffectedNode an : sortedAffectedNodes(tr)) { - Hash256 id = an.ledgerIndex(); - LedgerEntry le = an.nodeAsFinal(); - - if (an.isCreatedNode()) { - ledgerModifiedEntries.add(id); - ledgerDeletedEntries.remove(id); - le.setDefaults(); - state.addLE(le); - - if (le instanceof Offer) { - Offer offer = (Offer) le; - offer.setOfferDefaults(); // TODO / TODO - - for (Hash256 directory : offer.directoryIndexes()) { - DirectoryNode dn = getDirectoryForUpdating(directory); - Hash256 index = offer.index(); - addToDirectoryNode(dn, index); - } - } else if (le instanceof RippleState) { - RippleState state = (RippleState) le; - - for (Hash256 directory : state.directoryIndexes()) { - DirectoryNode dn = getDirectoryForUpdating(directory); - addToDirectoryNode(dn, state.index()); - } - } - - if (le instanceof IndexedLedgerEntry) { - IndexedLedgerEntry owned = (IndexedLedgerEntry) le; - for (Hash256 directory : owned.ownerDirectoryIndexes(tr.txn)) { - DirectoryNode dn = getDirectoryForUpdating(directory); - addToDirectoryNode(dn, owned.index()); - } - } - - if (le instanceof ThreadedLedgerEntry) { - ThreadedLedgerEntry tle = (ThreadedLedgerEntry) le; - tle.previousTxnID(tr.hash); - tle.previousTxnLgrSeq(tr.ledgerIndex); - } - } else if (an.isDeletedNode()) { - ledgerModifiedEntries.remove(id); - ledgerDeletedEntries.add(id); - directoriesModifiedMoreThanOnceByTransaction.remove(id); - state.removeLeaf(id); - if (le instanceof Offer) { - Offer offer = (Offer) le; - for (Hash256 directory : offer.directoryIndexes()) { - DirectoryNode dn = getDirectoryForUpdating(directory); - if (dn != null) { -// Hash256 index = offer.index(); - if (dn.owner() != null) { - deleteFromDirectoryUnstable(offer, dn); - } else { - deleteFromDirectoryStable(offer, dn); - } - } - } - } else if (le instanceof RippleState) { - RippleState state = (RippleState) le; - for (Hash256 directory : state.directoryIndexes()) { - DirectoryNode dn = getDirectoryForUpdating(directory); - if (dn != null) { - deleteFromDirectoryUnstable(le, dn); - } - } - } else if (le instanceof IndexedLedgerEntry) { - IndexedLedgerEntry owned = (IndexedLedgerEntry) le; - for (Hash256 directory : owned.ownerDirectoryIndexes(tr.txn)) { - DirectoryNode dn = getDirectoryForUpdating(directory); - deleteFromDirectoryUnstable(le, dn); - } - } - } else if (an.isModifiedNode()) { - ledgerModifiedEntries.add(id); - ShaMapLeaf leaf = state.getLeafForUpdating(id); - LedgerEntryItem item = (LedgerEntryItem) leaf.item; - LedgerEntry leModded = item.entry; - - if (le instanceof ThreadedLedgerEntry) { - ThreadedLedgerEntry tle = (ThreadedLedgerEntry) le; - tle.previousTxnID(tr.hash); - tle.previousTxnLgrSeq(tr.ledgerIndex); - } - for (Field field : le) { - // Already have the `index` - if (field == Field.LedgerIndex) { - continue; - } - leModded.put(field, le.get(field)); - } - // Find all removed fields - ArrayList removed = new ArrayList<>(); - for (Field field : leModded) { - if (an.removedField(field)) { - removed.add(field); - } - } - removed.forEach(leModded::remove); - } - } - } - - private void deleteFromDirectoryUnstable(LedgerEntry b4, DirectoryNode dn) { - boolean b = directoryRemoveUnstable(dn, b4.index()); - DirectoryNode cursor = dn; - - if (!b) { - while (cursor.indexNext() != null) { - cursor = getDirectoryForUpdating(cursor.nextIndex()); - b = directoryRemoveUnstable(cursor, b4.index()); - if (b) { - break; - } - } - } -// - if (!b) { - cursor = dn; - while (cursor.indexPrevious() != null) { - cursor = getDirectoryForUpdating(cursor.prevIndex()); - b = directoryRemoveUnstable(cursor, b4.index()); - if (b) { - break; - } - } - } - } - private void deleteFromDirectoryStable(LedgerEntry b4, DirectoryNode dn) { - boolean b = directoryRemoveStable(dn, b4.index()); - DirectoryNode cursor = dn; - - if (!b) { - while (cursor.hasIndexPrevious()) { - cursor = getDirectoryForUpdating(cursor.prevIndex()); - b = directoryRemoveStable(cursor, b4.index()); - if (b) { - break; - } - } - } - if (!b) { - while (cursor.indexNext() != null) { - cursor = getDirectoryForUpdating(cursor.nextIndex()); - b = directoryRemoveStable(cursor, b4.index()); - if (b) { - break; - } - } - } - } - - public static Collection makeCollection(Iterable iter) { - Collection list = new ArrayList<>(); - for (E item : iter) { - list.add(item); - } - return list; - } - private ArrayList sortedAffectedNodes(TransactionResult tr) { - ArrayList sorted = new ArrayList<>(makeCollection(tr.meta.affectedNodes())); - sorted.sort(Comparator.comparingInt(this::getOrdinal)); - return sorted; - } - - private int getOrdinal(AffectedNode o1) { - switch (o1.ledgerEntryType()) { - case DirectoryNode: - return 10; - case RippleState: - return 20; - case Offer: - return 30; - case Escrow: - case SignerList: - case PayChannel: - return 21; - default: - return 40; - } - } - - private void onDirectoryModified(DirectoryNode dn) { - Hash256 index = dn.index(); - if (directoriesModifiedByTransaction.contains(index)) { - directoriesModifiedMoreThanOnceByTransaction.add(index); - } - else { - directoriesModifiedByTransaction.add(index); - } - } - private boolean directoryRemoveStable(DirectoryNode dn, Hash256 index) { - onDirectoryModified(dn); - return dn.indexes().remove(index); - } - private boolean directoryRemoveUnstable(DirectoryNode dn, Hash256 index) { - onDirectoryModified(dn); - if (sortedDirectories) { - return dn.indexes().remove(index); - } else { - return dn.indexes().removeUnstable(index); - } - } - private void addToDirectoryNode(DirectoryNode dn, Hash256 index) { - onDirectoryModified(dn); - if (dn.exchangeRate() != null) { - dn.indexes().add(index); - } else { - dn.indexes().add(index); - if (sortedDirectories) { - Collections.sort(dn.indexes()); - } - } - } - private DirectoryNode getDirectoryForUpdating(Hash256 directoryIndex) { - ShaMapLeaf leaf = state.getLeafForUpdating(directoryIndex); - if (leaf == null) { - return null; - } - LedgerEntryItem lei = (LedgerEntryItem) leaf.item; - return (DirectoryNode) lei.entry; - } - - public AccountState state() { - return state; - } - - public long currentLedgerIndex() { - return targetLedgerIndex; - } - - public String targetAccountHashHex() { - return targetAccountHash.toHex(); - } - public Hash256 targetAccountHash() { - return targetAccountHash; - } - - public TreeSet directoriesWithIndexesOutOfOrder() { - TreeSet ret = new TreeSet<>(); - for (Hash256 hash256 : directoriesModifiedMoreThanOnceByTransaction) { - DirectoryNode dn = state.getDirectoryNode(hash256); - if (dn.owner() != null) { - ret.add(hash256); - } - } - return ret; - } - - public boolean bad() { - return !state.hash().equals(targetAccountHash); - } - - public AccountState previousState() { - return previousState; - } - - public void setState(AccountState map) { - state = map; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java deleted file mode 100644 index 11365302b5..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/BytesItem.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; - -public class BytesItem extends ShaMapItem { - private byte[] item; - - public BytesItem(byte[] item) { - this.item = item; - } - - @Override - void toBytesSink(BytesSink sink) { - sink.add(item); - } - - @Override - public ShaMapItem copy() { - return this; - } - - @Override - public byte[] value() { - return item; - } - - @Override - public Prefix hashPrefix() { - return new Prefix() { - @Override - public byte[] bytes() { - return new byte[0]; - } - }; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java deleted file mode 100644 index a565baf19b..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/HashedTreeWalker.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; - -public interface HashedTreeWalker { - public void onLeaf(Hash256 h, ShaMapLeaf le); - public void onInner(Hash256 h, ShaMapInner inner); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java deleted file mode 100644 index 71f371cebe..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/LeafWalker.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.ripple.core.types.shamap; - -public interface LeafWalker { - void onLeaf(ShaMapLeaf shaMapLeaf); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java deleted file mode 100644 index ea67d4bf0b..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryItem.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.STObject; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.fields.Field; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.types.known.sle.LedgerEntry; - -public class LedgerEntryItem extends ShaMapItem { - public LedgerEntryItem(LedgerEntry entry) { - this.entry = entry; - } - - public LedgerEntry entry; - - @Override - void toBytesSink(BytesSink sink) { - entry.toBytesSink(sink); - } - - @Override - public String toString() { - return entry.prettyJSON(); - } - - @Override - public ShaMapItem copy() { - STObject object = STObject.fromBytes(entry.toBytes()); - LedgerEntry le = (LedgerEntry) object; - // TODO: what about other auxiliary (non serialized) fields - le.index(entry.index()); - return new LedgerEntryItem(le); - } - - @Override - public LedgerEntry value() { - return entry; - } - - @Override - public Prefix hashPrefix() { - return HashPrefix.leafNode; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java deleted file mode 100644 index 6ce639b552..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/LedgerEntryVisitor.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.types.known.sle.LedgerEntry; - -public interface LedgerEntryVisitor { - public void onEntry(LedgerEntry entry); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java deleted file mode 100644 index 8d1bd98eee..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/NodeStore.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash256; - -/** - - * This is a toy implementation for illustrative purposes. - */ -public class NodeStore { - /** - * In ripple, all data is stored in a simple binary key/value database. - * The keys are 256 bit binary strings and the values are binary strings of - * arbitrary length. - */ - public static interface KeyValueBackend { - void put(Hash256 key, byte[] content); - byte[] get(Hash256 key); - } - - KeyValueBackend backend; - public NodeStore(KeyValueBackend backend) { - this.backend = backend; - } - /** - * All data stored is keyed by the hash of it's contents. - * Ripple uses the first 256 bits of a sha512 as it's 33 percent - * faster than using sha256. - * - * @return `key` used to store the content - */ - private Hash256 storeContent(byte[] content) { - HalfSha512 hasher = new HalfSha512(); - hasher.update(content); - Hash256 key = hasher.finish(); - storeHashKeyedContent(key, content); - return key; - } - - /** - * @param hash As ripple uses the `hash` of the contents as the - * NodeStore key, `hash` is pervasively used in lieu of - * the term `key`. - */ - private void storeHashKeyedContent(Hash256 hash, byte[] content) { - // Note: The real nodestore actually prepends some metadata, which doesn't - // contribute to the hash. - backend.put(hash, content); // metadata + content - } - - /** - * The complement to `set` api, which together form a simple public interface. - */ - public byte[] get(Hash256 hash) { - return backend.get(hash); - - } - /** - * The complement to `get` api, which together form a simple public interface. - */ - public Hash256 set(byte[] content) { - return storeContent(content); - } -} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java deleted file mode 100644 index dcc0dfd56e..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/PathToIndex.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Iterator; - -public class PathToIndex { - public Hash256 index; - public ShaMapLeaf leaf; - - private ArrayDeque inners; - private ShaMapInner[] dirtied; - private boolean matched = false; - - public boolean hasLeaf() { - return leaf != null; - } - public boolean leafMatchedIndex() { - return matched; - } - public boolean copyLeafOnUpdate() { - return leaf.version != dirtied[0].version; - } - - int size() { - return inners.size(); - } - - public ShaMapInner top() { - return dirtied[dirtied.length - 1]; - } - - // returns the - public ShaMapInner dirtyOrCopyInners() { - if (maybeCopyOnWrite()) { - int ix = 0; - // We want to make a uniformly accessed array of the inners - dirtied = new ShaMapInner[inners.size()]; - // from depth 0 to 1, to 2, to 3, don't be fooled by the api - Iterator it = inners.descendingIterator(); - - // This is actually the root which COULD be the top of the stack - // Think about it ;) - ShaMapInner top = it.next(); - dirtied[ix++] = top; - top.invalidate(); - - while (it.hasNext()) { - ShaMapInner next = it.next(); - boolean doCopies = next.version != top.version; - - if (doCopies) { - ShaMapInner copy = next.copy(top.version); - copy.invalidate(); - top.setBranch(index, copy); - next = copy; - } else { - next.invalidate(); - } - top = next; - dirtied[ix++] = top; - } - return top; - } else { - copyInnersToDirtiedArray(); - return inners.peekFirst(); - } - } - - public boolean hasMatchedLeaf() { - return hasLeaf() && leafMatchedIndex(); - } - - public void collapseOnlyLeafChildInners() { - assert dirtied != null; - - ShaMapInner next; - ShaMapLeaf onlyChild = null; - - for (int i = dirtied.length - 1; i >= 0; i--) { - next = dirtied[i]; - if (onlyChild != null) { - next.setLeaf(onlyChild); - } - onlyChild = next.onlyChildLeaf(); - if (onlyChild == null) { - break; - } - } - } - - private void copyInnersToDirtiedArray() { - int ix = 0; - dirtied = new ShaMapInner[inners.size()]; - Iterator descending = inners.descendingIterator(); - while (descending.hasNext()) { - ShaMapInner next = descending.next(); - dirtied[ix++] = next; - next.invalidate(); - } - } - - private boolean maybeCopyOnWrite() { - return inners.peekLast().doCoW; - } - - public PathToIndex(ShaMapInner root, Hash256 index) { - this.index = index; - makeStack(root, index); - } - - private void makeStack(ShaMapInner root, Hash256 index) { - inners = new ArrayDeque<>(); - ShaMapInner top = root; - - while (true) { - inners.push(top); - ShaMapNode existing = top.getBranch(index); - if (existing == null) { - break; - } else if (existing.isLeaf()) { - leaf = existing.asLeaf(); - matched = leaf.index.equals(index); - break; - } - else if (existing.isInner()) { - top = existing.asInner(); - } - } - } - - public ShaMapLeaf invalidatedPossiblyCopiedLeafForUpdating() { - assert matched; - if (dirtied == null) { - dirtyOrCopyInners(); - } - ShaMapLeaf theLeaf = leaf; - - if (copyLeafOnUpdate()) { - theLeaf = leaf.copy(); - top().setLeaf(theLeaf); - } - theLeaf.invalidate(); - return theLeaf; - } - - public ArrayList topDownList() { - ArrayList path = new ArrayList<>(); - Iterator shaMapInnerIterator = inners.descendingIterator(); - shaMapInnerIterator.forEachRemaining(path::add); - path.add(leaf); - return path; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md b/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md deleted file mode 100644 index a78bc3ad73..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/README.md +++ /dev/null @@ -1,319 +0,0 @@ -Rippled NodeStore ------------------ - -To understand a ShaMap first you must know about the NodeStore. - -```java -/** - - * This is a toy implementation for illustrative purposes. - */ -public class NodeStore { - /** - * In ripple, all data is stored in a simple binary key/value database. - * The keys are 256 bit binary strings and the values are binary strings of - * arbitrary length. - */ - public interface KeyValueBackend { - void put(Hash256 key, byte[] content); - byte[] get(Hash256 key); - } - - KeyValueBackend backend; - public NodeStore(KeyValueBackend backend) { - this.backend = backend; - } - /** - * All data stored is keyed by the hash of it's contents. - * Ripple uses the first 256 bits of a sha512 as it's 33 percent - * faster than using sha256. - * - * @return `key` used to store the content - */ - private Hash256 storeContent(byte[] content) { - Hash256.HalfSha512 hasher = new Hash256.HalfSha512(); - hasher.update(content); - Hash256 key = hasher.finish(); - storeHashKeyedContent(key, content); - return key; - } - - /** - * @param hash As ripple uses the `hash` of the contents as the - * NodeStore key, `hash` is pervasively used in lieu of - * the term `key`. - */ - private void storeHashKeyedContent(Hash256 hash, byte[] content) { - // Note: The real NodeStore actually prepends some metadata, which doesn't - // contribute to the hash. - backend.put(hash, content); // metadata + content - } - - /** - * The complement to `set` api, which together form a simple public interface. - */ - public byte[] get(Hash256 hash) { - return backend.get(hash); - - } - /** - * The complement to `get` api, which together form a simple public interface. - */ - public Hash256 set(byte[] content) { - return storeContent(content); - } -} -``` - -See also: -* [Serialized Types](../../../../../../../../README.md) -* [BinaryFormats.txt (historical)](https://github.com/ripple/rippled/blob/07df5f1f81b0ee1ab641d134ba8e940a90f5297e/BinaryFormats.txt#L2-L6) - -Excerpt from BinaryFormats.txt (historical): - -
- All signed or hashed objects must have well-defined binary formats at the - byte level. These formats do not have to be the same as the network wire - formats or the forms used for efficient storage or human display. However, - it must always be possible to precisely re-create, byte for byte, any signed - or hashed object. Otherwise, the signatures or hashes cannot be validated. -
- -Note that currently (26/Jan/2018) the NodeStore stores it in the hashing form. - -What is a ShaMap? ------------------ - -A ShaMap is a special type of tree, used as a way to index values stored in a -`NodeStore` - -Recall that values in the NodeStore are keyed by the hash of their contents. - -But what about identities that change over time? How can you retrieve a certain -version of something? What could be used as an enduring identifier? The value -must have some component[s] that are static over time. These are fed into a -hashing function to create a 256 bit identifier. - -But how is this used? You can only query values by `hash` in the NodeStore. The -hash, as a function of a value would obviously change along with it. - -The identifier is used as an `index` into a ShaMap tree, which in ripple, is -representative of a point in time. In fact a ShaMap can be hashed -deterministically, thus a point in time can be identified by a `hash`. Where is -a ShaMap actually stored? In the NodeStore, of course. - -But the NodeStore only stores binary content you protest! But the ShaMap has a -binary representation! So what are the `contents` of a ShaMap, to be hashed to -be stored in the NodeStore? - -Glad you asked. A tree, has a root, and many children, either more branches, or -terminal leaves. The root, and any of its children that have children -themselves, are classed as `inner nodes`. - -In a ShaMap these `inner nodes` each have 16 `slots` for children. The binary -representation of these is simply 16 `hash`es, used to retrieve child nodes from -the NodeStore. - -An example of an inner node's `contents` - - Empty slots are represented as 32 0 bytes - - ``` - 022CC592F5D4ABC3A63DA2A036CDDC0825B30717C78EF287BEF200056133FDA2 - 0000000000000000000000000000000000000000000000000000000000000000 - BEE626551799DDFE65BD2D9A0F0EA24D72C93CFD8E083176718D2B079EC60214 - E1B34F1D9209CB668A50CCEE71C8109D140A6D715D923AEE98E6D53015D8B66B - 4C27A856094CFDE37CD2A0EA93DADB595B10CFEC55F816C987A6AC48D13AF5C0 - 2F770714A9EF92792F44AA1537C18F68AFE3FFF157FB9088FFE2BDA695C19B71 - C915CA982310CF41CF1266AA43C3B31ACBF4304D05ADB54A352D942C890763A3 - F29FAD442CE204513BEA555A4192E324407444D946449CEA510C37A9BB982134 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 44B3BE10744EA2DA010D530C6AE64E3C3984DA7701EE79A66EA429EC11B87D1D - 0C7BE8569E9F08BADDEB91EBE79E5B98BBF245B067B7B83B4A95430CFEC9F7E8 - BB38EA169DB6A020EA820BD1242DDB6250B397A26015507BA3C7F3C041EA683C - 0000000000000000000000000000000000000000000000000000000000000000 - 15B98934D22B5CB7233C42CE8DC8DD0D2328AB91CC574332C45D7160BD31D4AD - 1894E389AE4A63BA99C2D0546A58A976ECDAB14C09B98F532999B464696E29E5 - ``` - -What about those `index` thingies again? Remember, the `index` can't be used to -query something directly in the NodeStore. - -First you need a known point in time, which we learned could be defined by a -`hash` of a ShaMap. - -* shamap hash: 2F049AEE51C7C96AB911AF86E3278F4F90A38D196422A832617FF0C6F29C3704 -* value index: FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB - -Imagine we have those above. First we query the NodeStore with `2F049A...` - -What do we expect back? A ShaMap hash is the hash of the binary representation -of the root node (which is an `inner node`) of the tree, so we'd expect -something in the form shown earlier, with 16 256 bit hashes. - -From the NodeStore we retrieve: - - ``` - 4D494E00 - 3C926652404076CA35EA1D89580975C50DCD0B29EC16079F168BE63BB1D6F237 - F0D3F178C56C438C597D53FF5E3D44EE3865C17A0D25DCC2460F20BE4BEB4B7E - D65D6CA291E451E6D6566A5431D755A749D9B0450E83B376148A6F93349ACD46 - 309B18093008055BE23E118DA4243DFC9AEF66E3260E2008BD6E6E6806F06725 - 0000000000000000000000000000000000000000000000000000000000000000 - D7D5A7C89DAE6D7517EDCB0601829CB339376EECD1DE8CA0216B6C18FFD77C32 - 7C33AEB525B09A7BC013C01015D59A88129A8A6C18B45E6D7D0CA1F13E6FCB44 - AB35119A7529D4BA57C41D7020833A0E9600895F61E9E9DEABBFDF82A877CBB2 - 3BE7A48570263034E6DCBEFA6ED57B63C0592AE145341A79DAF57C3BDF7C5793 - 17006AD967A1536E0441517990AD5B42890A3168AC9E045EAF9AC5A06F672561 - 94B12B8BB76D525DD9320AF51893A6D69FF730C1E647181E7A7B51FE1FBF369E - 0579A72B3209AE66840F6E8317F422F43937E6AE1A14C8B30243DE016551643F - B873AA4EF1CDF0332C59BE423256610C4C6A1D32E2A1F8DE748390E29E8FC2D3 - EB03A93BBC95ED56FB73E6FBDAB8F6916BBD1BD358336CBA4DA673558F5B068C - E64A78A07CF33C3B74AEA9862B5758513677324D4C9D72C69D14B4EB64D4EB02 - 4E8C0CE75693B85A4CAC5516B77702E660A55281CF17DBE09552941F3078D81C - ``` - -We see the hashes for 16 nodes clear as day, but what is this `4D494E00` -prefixed to the front? Converted to `ascii` letters the hex `4D494E00` is -`MIN\x00`, meaning sham)ap i)nner n)ode. - -The prefix `namespaces` the content, so different classes of objects which -would otherwise have the same binary representation, will have a different -`hash`. These `hash prefixes` serve another useful purpose, as we'll see later. -(Similarly, there are namespacing prefixes for an `index` (created by - feeding static components of an identity into a hashing function)) - -Is our value `index` hash amongst those enumerated? No !!! So what do we do with -it? An index, usually means an ordinal, defining a place in an array. The -`index` is actually an index into 64 arrays. Each nibble in the `index` is an -index into the 16 slots in each inner node. - -Consider again the value `index`: - - `FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB` - -To use the `index` we take the first nibble, `F` (yes, we go left to right) - -The letter `F` in hex has the ordinal value 15, so we take the 16th branch (0 -based indexing) - -We select the 16th hash - - `4E8C0CE75693B85A4CAC5516B77702E660A55281CF17DBE09552941F3078D81C` - -From the NodeStore we retrieve: - - ``` - 4D494E00 - 0000000000000000000000000000000000000000000000000000000000000000 - 286BC64A4A369857E4B0B5834C54CED797110D06E64F7759FBA2C87D3630D418 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 60631B91674954D21314B89CEE3B7F740B4FB1374610498EA1A7A3B79BA6706D - 3B1C36A6311256FE1E72BEDBA2042D67D86F561E51B387CFA680BCE9982CD6DB - 5568E7032EE018CA484C181CD68411B623229D0666AE0038708500C59402A282 - 0000000000000000000000000000000000000000000000000000000000000000 - ``` - -There's that 'MIN\x00` hash prefix again. - -In fact, this prefix is how we can deterministically say that this is an -`inner node` and that we can interpret the following bytes as 16 more -`hash`es. - -We have descended deeper into the tree, but it seems we need to go deeper. We -are currently at a depth of 2, so to go deeper we need the 2nd nibble. - -value index: - ``` - FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB` - | - \ - 2nd nibble - ``` - -The letter `E` in hex has the ordinal value 14, so we take the 15th branch (0 -based indexing) - -We select the 15th hash: - - `5568E7032EE018CA484C181CD68411B623229D0666AE0038708500C59402A282` - -From the NodeStore we retrieve: - - ``` - 534E4400 - C11C12000722800000002400AA7BFF201900AA7BFC201B0226FF9464D4461B5C - A191A906000000000000000000000000455448000000000006CC4A6D023E68AA - 3499C6DE3E9F2DC52B8BA25465400000000861014A6840000000000000C17321 - 03CF1DFB34A96363FF2B91638FCE51E6D7B88419729E9A81ABC99A9512FFB9C7 - 3374463044022005ED4635AE246A4060378D9396CAA0E42F7E9129D309B2E98B - DF5CE2352520A002207D4494019EA4327F4087EA34B05CE9E5CD0AE3082BAD77 - CC3698CE5A59C21BD581140BEC53D0830ADCE9E372086E570809916C440E83C3 - F4201C00000033F8E311006F561BF352EEDB9072286286A4BBC8C419C995A171 - 0AA0CFA8B0D2B843F07D294F60E82400AA7BFF501090B86A84C7F7843673BCF8 - 2E565E69498CAEF463F8055ABA4C04581E76C9270064D4461B5CA191A9060000 - 00000000000000000000455448000000000006CC4A6D023E68AA3499C6DE3E9F - 2DC52B8BA25465400000000861014A81140BEC53D0830ADCE9E372086E570809 - 916C440E83E1E1E31100645690B86A84C7F7843673BCF82E565E69498CAEF463 - F8055ABA4C04581E76C92700E8364C04581E76C927005890B86A84C7F7843673 - BCF82E565E69498CAEF463F8055ABA4C04581E76C92700011100000000000000 - 00000000004554480000000000021106CC4A6D023E68AA3499C6DE3E9F2DC52B - 8BA254E1E1E41100645690B86A84C7F7843673BCF82E565E69498CAEF463F805 - 5ABA4C045835BF30CCBFE72200000000364C045835BF30CCBF5890B86A84C7F7 - 843673BCF82E565E69498CAEF463F8055ABA4C045835BF30CCBF011100000000 - 00000000000000004554480000000000021106CC4A6D023E68AA3499C6DE3E9F - 2DC52B8BA2540311000000000000000000000000000000000000000004110000 - 000000000000000000000000000000000000E1E1E411006F56AE4B62A73DC540 - 40E523FCE863981AB601B6D6BCD3CFCE303B43A430FC6D4DB1E7220000000024 - 00AA7BFC250226FF9133000000000000000034000000000000000055B61A418E - 421021CFBA22B02F4934B4F79B1091F91CF910AEB21DA0975CEC52AB501090B8 - 6A84C7F7843673BCF82E565E69498CAEF463F8055ABA4C045835BF30CCBF64D4 - 461B7D5C693EDF000000000000000000000000455448000000000006CC4A6D02 - 3E68AA3499C6DE3E9F2DC52B8BA25465400000000861014A81140BEC53D0830A - DCE9E372086E570809916C440E83E1E1E511006456B937CC88FCAF18886CC8D4 - B19A5326F56B0B84E06AE511407B072DE348E05376E722000000003100000000 - 0000000032000000000000000058B937CC88FCAF18886CC8D4B19A5326F56B0B - 84E06AE511407B072DE348E0537682140BEC53D0830ADCE9E372086E57080991 - 6C440E83E1E1E5110061250226FF915558E2CDAB1D8D5477D8FED6EA5EFD9F9F - D8FAC56EA907E94197900C6C6175CE9556E9293AF964F2B20467530673C8F327 - 41ED03DEF52F6B6625B4D837C155856C26E62400AA7BFF6240000000B60EBC57 - E1E722000000002400AA7C002D000000186240000000B60EBB9681140BEC53D0 - 830ADCE9E372086E570809916C440E83E1E1F1031000 - FEEE5CC92B64375C8FEE56D54A82B9965E44FE0DCF673DBF27D0AA93F8AFF4FB - ``` - -Well, here's something new. The `hash prefix` is different. This time the -hex decodes as `MLN\x00`, meaning sham)ap l)eaf n)ode. - -And what's that at the end? Is that our index? It is!! - -Why does it need to be stored? We have only used `FE` to traverse to this -node. Without storing the `index` identifier in the leaf node contents, -there would be no way to be certain that this leaf held the item you wanted. -More importantly, it acts as further name-spacing, to prevent collisions. -(Technically, you could synthesize the index, by parsing the contents of -the object and recreating it) - -Takeaways ---------- - -* A `hash` keys the NodeStore -* An `index` is a path to an item in a ShaMap -* For communication purposes - - Always use `hash` when referring to a key for the NodeStore - - Always use `index` when referring to a key for a ShaMap - -Links ------ - -* [Rippled Hash Prefix declarations](../../coretypes/hash/prefixes/HashPrefix.java) \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java deleted file mode 100644 index 0129eb7c4a..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMap.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ripple.core.types.shamap; - -import java.util.concurrent.atomic.AtomicInteger; - -public class ShaMap extends ShaMapInner { - private AtomicInteger copies; - - public ShaMap() { - super(0); - // This way we can copy the first to the second, - // copy the second, then copy the first again ;) - copies = new AtomicInteger(); - } - public ShaMap(boolean isCopy, int depth) { - super(isCopy, depth, 0); - } - - @Override - protected ShaMapInner makeInnerOfSameClass(int depth) { - return new ShaMap(true, depth); - } - - public ShaMap copy() { - version = copies.incrementAndGet(); - ShaMap copy = (ShaMap) copy(copies.incrementAndGet()); - copy.copies = copies; - return copy; - } - -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java deleted file mode 100644 index 41e23d50e1..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapDiff.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; - -import java.util.TreeSet; - -public class ShaMapDiff { - public ShaMap one, two; - - public TreeSet modified = new TreeSet<>(); - public TreeSet deleted = new TreeSet<>(); - public TreeSet added = new TreeSet<>(); - - public ShaMapDiff(ShaMap one, ShaMap two) { - this.one = one; - this.two = two; - } - - // Find what's added, modified and deleted in `two` - public ShaMapDiff find() { - one.hash(); - two.hash(); - compare(one, two); - return this; - } - - public ShaMapDiff inverted() { - ShaMapDiff shaMapDiff = new ShaMapDiff(two, one); - - shaMapDiff.added = deleted; - shaMapDiff.modified = modified; - shaMapDiff.deleted = added; - - return shaMapDiff; - } - - public void apply(ShaMap sa) { - for (Hash256 mod : modified) { - boolean modded = sa.updateItem(mod, two.getItem(mod).copy()); - if (!modded) throw new AssertionError(); - } - - for (Hash256 add : added) { - boolean added = sa.addItem(add, two.getItem(add).copy()); - if (!added) throw new AssertionError(); - } - for (Hash256 delete : deleted) { - boolean removed = sa.removeLeaf(delete); - if (!removed) throw new AssertionError(); - } - } - private void compare(ShaMapInner a, ShaMapInner b) { - for (int i = 0; i < 16; i++) { - ShaMapNode aChild = a.getBranch(i); - ShaMapNode bChild = b.getBranch(i); - - if (aChild == null && bChild != null) { - trackAdded(bChild); - // added in B - } else if (aChild != null && bChild == null) { - trackRemoved(aChild); - // removed from B - } else if (aChild != null && !aChild.hash().equals(bChild.hash())) { - boolean aleaf = aChild.isLeaf(), - bLeaf = bChild.isLeaf(); - - if (aleaf && bLeaf) { - ShaMapLeaf la = (ShaMapLeaf) aChild; - ShaMapLeaf lb = (ShaMapLeaf) bChild; - if (la.index.equals(lb.index)) { - modified.add(la.index); - } else { - deleted.add(la.index); - added.add(lb.index); - } - } else if (aleaf /*&& bInner*/) { - ShaMapLeaf la = (ShaMapLeaf) aChild; - ShaMapInner ib = (ShaMapInner) bChild; - trackAdded(ib); - - //noinspection Duplicates - if (ib.hasLeaf(la.index)) { - // because trackAdded would have added it - added.remove(la.index); - ShaMapLeaf leaf = ib.getLeaf(la.index); - if (!leaf.hash().equals(la.hash())) { - modified.add(la.index); - } - } else { - deleted.add(la.index); - } - } else if (bLeaf /*&& aInner*/) { - ShaMapLeaf lb = (ShaMapLeaf) bChild; - ShaMapInner ia = (ShaMapInner) aChild; - trackRemoved(ia); - - //noinspection Duplicates - if (ia.hasLeaf(lb.index)) { - // because trackRemoved would have deleted it - deleted.remove(lb.index); - ShaMapLeaf leaf = ia.getLeaf(lb.index); - if (!leaf.hash().equals(lb.hash())) { - modified.add(lb.index); - } - } else { - added.add(lb.index); - } - } else /*if (aInner && bInner)*/ { - compare((ShaMapInner) aChild, (ShaMapInner) bChild); - } - } - } - } - - private void trackRemoved(ShaMapNode child) { - child.walkAnyLeaves(leaf -> deleted.add(leaf.index)); - } - - private void trackAdded(ShaMapNode child) { - child.walkAnyLeaves(leaf -> added.add(leaf.index)); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java deleted file mode 100644 index f7d73dae65..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapInner.java +++ /dev/null @@ -1,331 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; - -import java.util.Iterator; - -public class ShaMapInner extends ShaMapNode implements Iterable { - public int depth; - int slotBits = 0; - int version = 0; - boolean doCoW; - protected ShaMapNode[] branches = new ShaMapNode[16]; - - public ShaMapInner(int depth) { - this(false, depth, 0); - } - - public ShaMapInner(boolean isCopy, int depth, int version) { - this.doCoW = isCopy; - this.depth = depth; - this.version = version; - } - - protected ShaMapInner copy(int version) { - ShaMapInner copy = makeInnerOfSameClass(depth); - System.arraycopy(branches, 0, copy.branches, 0, branches.length); - copy.slotBits = slotBits; - copy.hash = hash; - copy.version = version; - doCoW = true; - - return copy; - } - - protected ShaMapInner makeInnerOfSameClass(int depth) { - return new ShaMapInner(true, depth, version); - } - - protected ShaMapInner makeInnerChild() { - int childDepth = depth + 1; - if (childDepth >= 64) throw new AssertionError(); - return new ShaMapInner(doCoW, childDepth, version); - } - - // Descend into the tree, find the leaf matching this index - // and if the tree has it. - protected void setLeaf(ShaMapLeaf leaf) { - if (leaf.version == -1) { - leaf.version = version; - } - setBranch(leaf.index, leaf); - } - - private void removeBranch(Hash256 index) { - removeBranch(selectBranch(index)); - } - - public void walkLeaves(LeafWalker leafWalker) { - for (ShaMapNode branch : branches) { - if (branch != null) { - if (branch.isInner()) { - branch.asInner().walkLeaves(leafWalker); - } else if (branch.isLeaf()) { - leafWalker.onLeaf(branch.asLeaf()); - } - } - } - } - - public void walkTree(TreeWalker treeWalker) { - treeWalker.onInner(this); - for (ShaMapNode branch : branches) { - if (branch != null) { - if (branch.isLeaf()) { - ShaMapLeaf ln = branch.asLeaf(); - treeWalker.onLeaf(ln); - } else if (branch.isInner()) { - ShaMapInner childInner = branch.asInner(); - childInner.walkTree(treeWalker); - } - } - } - - } - - public void walkHashedTree(HashedTreeWalker walker) { - walker.onInner(hash(), this); - - for (ShaMapNode branch : branches) { - if (branch != null) { - if (branch.isLeaf()) { - ShaMapLeaf ln = branch.asLeaf(); - walker.onLeaf(branch.hash(), ln); - } else if (branch.isInner()) { - ShaMapInner childInner = branch.asInner(); - childInner.walkHashedTree(walker); - } - } - } - } - - /** - * @return the `only child` leaf or null if other children - */ - public ShaMapLeaf onlyChildLeaf() { - ShaMapLeaf leaf = null; - int leaves = 0; - - for (ShaMapNode branch : branches) { - if (branch != null) { - if (branch.isInner()) { - leaf = null; - break; - } else if (++leaves == 1) { - leaf = branch.asLeaf(); - } else { - leaf = null; - break; - } - } - } - return leaf; - } - - public boolean removeLeaf(Hash256 index) { - PathToIndex path = pathToIndex(index); - if (path.hasMatchedLeaf()) { - ShaMapInner top = path.dirtyOrCopyInners(); - top.removeBranch(index); - path.collapseOnlyLeafChildInners(); - return true; - } else { - return false; - } - } - - public ShaMapItem getItem(Hash256 index) { - ShaMapLeaf leaf = getLeaf(index); - - @SuppressWarnings("unchecked") - ShaMapItem shaMapItem = leaf == null ? null : leaf.item; - return shaMapItem; - } - - public boolean addItem(Hash256 index, ShaMapItem item) { - return addLeaf(new ShaMapLeaf(index, item)); - } - - public boolean updateItem(Hash256 index, ShaMapItem item) { - return updateLeaf(new ShaMapLeaf(index, item)); - } - - public boolean hasLeaf(Hash256 index) { - return pathToIndex(index).hasMatchedLeaf(); - } - - public ShaMapLeaf getLeaf(Hash256 index) { - PathToIndex stack = pathToIndex(index); - if (stack.hasMatchedLeaf()) { - return stack.leaf; - } else { - return null; - } - } - - public boolean addLeaf(ShaMapLeaf leaf) { - PathToIndex stack = pathToIndex(leaf.index); - if (stack.hasMatchedLeaf()) { - return false; - } else { - ShaMapInner top = stack.dirtyOrCopyInners(); - top.addLeafToTerminalInner(leaf); - return true; - } - } - - public boolean updateLeaf(ShaMapLeaf leaf) { - PathToIndex stack = pathToIndex(leaf.index); - if (stack.hasMatchedLeaf()) { - ShaMapInner top = stack.dirtyOrCopyInners(); - // Why not update in place? Because of structural sharing - top.setLeaf(leaf); - return true; - } else { - return false; - } - } - - public PathToIndex pathToIndex(Hash256 index) { - return new PathToIndex(this, index); - } - - /** - * This should only be called on the deepest inners, as it - * does not do any dirtying. - * @param leaf to add to inner - */ - void addLeafToTerminalInner(ShaMapLeaf leaf) { - ShaMapNode branch = getBranch(leaf.index); - if (branch == null) { - setLeaf(leaf); - } else if (branch.isInner()) { - // This should never be called - throw new AssertionError(); - } else if (branch.isLeaf()) { - ShaMapInner inner = makeInnerChild(); - setBranch(leaf.index, inner); - inner.addLeafToTerminalInner(leaf); - inner.addLeafToTerminalInner(branch.asLeaf()); - } - } - - protected void setBranch(Hash256 index, ShaMapNode node) { - setBranch(selectBranch(index), node); - } - - protected ShaMapNode getBranch(Hash256 index) { - return getBranch(index.nibblet(depth)); - } - - public ShaMapNode getBranch(int i) { - return branches[i]; - } - - public ShaMapNode branch(int i) { - return branches[i]; - } - - protected int selectBranch(Hash256 index) { - return index.nibblet(depth); - } - - public boolean hasLeaf(int i) { - return branches[i].isLeaf(); - } - public boolean hasInner(int i) { - return branches[i].isInner(); - } - public boolean hasNone(int i) {return branches[i] == null;} - - private void setBranch(int slot, ShaMapNode node) { - slotBits = slotBits | (1 << slot); - branches[slot] = node; - invalidate(); - } - - private void removeBranch(int slot) { - branches[slot] = null; - slotBits = slotBits & ~(1 << slot); - } - public boolean empty() { - return slotBits == 0; - } - - @Override public boolean isLeaf() { return false; } - @Override public boolean isInner() { return true; } - - @Override - Prefix hashPrefix() { - return HashPrefix.innerNode; - } - - @Override - public void toBytesSink(BytesSink sink) { - for (ShaMapNode branch : branches) { - if (branch != null) { - branch.hash().toBytesSink(sink); - } else { - Hash256.ZERO_256.toBytesSink(sink); - } - } - } - - @Override - public Hash256 hash() { - if (empty()) { - // empty inners have a hash of all ZERO - // it's only valid for a root node to be empty - // any other inner node, must contain at least a - // single leaf - assert depth == 0; - return Hash256.ZERO_256; - } else { - // hash the hashPrefix() and toBytesSink - return super.hash(); - } - } - - public ShaMapLeaf getLeafForUpdating(Hash256 leaf) { - PathToIndex path = pathToIndex(leaf); - if (path.hasMatchedLeaf()) { - return path.invalidatedPossiblyCopiedLeafForUpdating(); - } - return null; - } - - @Override - public Iterator iterator() { - return new Iterator() { - int ix = 0; - - @Override - public boolean hasNext() { - return ix != 16; - } - - @Override - public ShaMapNode next() { - return branch(ix++); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - public int branchCount() { - int populated = 0; - for (ShaMapNode branch : branches) { - if (branch != null) { - populated ++; - } - } - return populated; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java deleted file mode 100644 index a8ec303dbb..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapItem.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; - -abstract public class ShaMapItem { - abstract void toBytesSink(BytesSink sink); - public abstract ShaMapItem copy(); - public abstract T value(); - public abstract Prefix hashPrefix(); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java deleted file mode 100644 index 3a79dacb94..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapLeaf.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; - -public class ShaMapLeaf extends ShaMapNode { - public Hash256 index; - public ShaMapItem item; - public long version = -1; - - protected ShaMapLeaf(Hash256 index, ShaMapItem item) { - this.index = index; - this.item = item; - } - - @Override public boolean isLeaf() {return true;} - @Override public boolean isInner() {return false;} - - @Override - Prefix hashPrefix() { - return item.hashPrefix(); - } - - @Override - public void toBytesSink(BytesSink sink) { - item.toBytesSink(sink); - index.toBytesSink(sink); - } - - public ShaMapLeaf copy() { - return new ShaMapLeaf(index, item.copy()); - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java deleted file mode 100644 index c5e6d00aca..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/ShaMapNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.HalfSha512; -import com.ripple.core.coretypes.hash.Hash256; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BytesSink; - -abstract public class ShaMapNode { - protected Hash256 hash; - - // This saves a lot of instanceof checks - public abstract boolean isLeaf(); - public abstract boolean isInner(); - - public ShaMapLeaf asLeaf() { - return (ShaMapLeaf) this; - } - public ShaMapInner asInner() { - return (ShaMapInner) this; - } - - abstract Prefix hashPrefix(); - abstract public void toBytesSink(BytesSink sink); - - public void invalidate() {hash = null;} - public Hash256 hash() { - if (hash == null) { - hash = createHash(); - } - return hash; - } - private Hash256 createHash() { - HalfSha512 half = HalfSha512.prefixed256(hashPrefix()); - toBytesSink(half); - return half.finish(); - } - /** - * Walk any leaves, possibly this node itself, if it's terminal. - */ - public void walkAnyLeaves(LeafWalker leafWalker) { - if (isLeaf()) { - leafWalker.onLeaf(asLeaf()); - } else { - asInner().walkLeaves(leafWalker); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java deleted file mode 100644 index 9e4d34a39d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultItem.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.coretypes.hash.prefixes.HashPrefix; -import com.ripple.core.coretypes.hash.prefixes.Prefix; -import com.ripple.core.serialized.BinarySerializer; -import com.ripple.core.serialized.BytesSink; -import com.ripple.core.types.known.tx.result.TransactionResult; - -public class TransactionResultItem extends ShaMapItem { - public TransactionResult result; - - public TransactionResultItem(TransactionResult result) { - this.result = result; - } - - @Override - void toBytesSink(BytesSink sink) { - BinarySerializer write = new BinarySerializer(sink); - write.addLengthEncoded(result.txn); - write.addLengthEncoded(result.meta); - } - - @Override - public ShaMapItem copy() { - // that's ok right ;) these bad boys are immutable anyway - return this; - } - - @Override - public TransactionResult value() { - return result; - } - - @Override - public Prefix hashPrefix() { - return HashPrefix.txNode; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java deleted file mode 100644 index 3993b3795d..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionResultVisitor.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ripple.core.types.shamap; -import com.ripple.core.types.known.tx.result.TransactionResult; - -public interface TransactionResultVisitor { - public void onTransaction(TransactionResult tx); -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java deleted file mode 100644 index 72c4ac4ddc..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/TransactionTree.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ripple.core.types.shamap; - -import com.ripple.core.types.known.tx.result.TransactionResult; - -import java.util.TreeSet; - -public class TransactionTree extends ShaMap { - public TransactionTree() { - super(); - } - - public TransactionTree(boolean isCopy, int depth) { - super(isCopy, depth); - } - - @Override - protected ShaMapInner makeInnerOfSameClass(int depth) { - return new TransactionTree(true, depth); - } - - public void addTransactionResult(TransactionResult tr) { - TransactionResultItem item = new TransactionResultItem(tr); - addItem(tr.hash, item); - } - - @Override - public TransactionTree copy() { - return (TransactionTree) super.copy(); - } - - public void walkTransactions(final TransactionResultVisitor walker) { - walkLeaves(leaf -> { - TransactionResultItem item = (TransactionResultItem) leaf.item; - walker.onTransaction(item.result); - }); - } - - public TreeSet toTreeSet() { - TreeSet result = new TreeSet<>(); - walkTransactions(result::add); - return result; - } -} diff --git a/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java b/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java deleted file mode 100644 index de225e9eaf..0000000000 --- a/ripple-core/src/main/java/com/ripple/core/types/shamap/TreeWalker.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ripple.core.types.shamap; - -public interface TreeWalker { - public void onLeaf(ShaMapLeaf leaf); - public void onInner(ShaMapInner inner); -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/Seed.java b/ripple-core/src/main/java/com/ripple/crypto/Seed.java deleted file mode 100644 index 5c0231828f..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/Seed.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.ripple.crypto; - -import com.ripple.crypto.ecdsa.K256; -import com.ripple.crypto.ed25519.EDKeyPair; -import com.ripple.crypto.keys.IKeyPair; -import com.ripple.encodings.addresses.Addresses; -import com.ripple.encodings.base58.B58; -import com.ripple.utils.Sha512; - -import java.io.UnsupportedEncodingException; -import java.util.Arrays; - -public class Seed { - private final byte[] seedBytes; - private B58.Version version; - - public Seed(byte[] seedBytes) { - this(Addresses.SEED_K256, seedBytes); - } - - public Seed(B58.Version version, byte[] seedBytes) { - this.seedBytes = seedBytes; - this.version = version; - } - - @Override - public String toString() { - return Addresses.encode(seedBytes, version); - } - - public byte[] bytes() { - return seedBytes; - } - - public B58.Version version() { - return version; - } - - public Seed setEd25519() { - this.version = Addresses.SEED_ED25519; - return this; - } - - public IKeyPair keyPair() { - return keyPair(0); - } - - public IKeyPair rootKeyPair() { - return keyPair(-1); - } - - public IKeyPair keyPair(int account) { - if (version == Addresses.SEED_ED25519 || - Arrays.equals(version.bytes, Addresses.SEED_ED25519.bytes)) { - if (account != 0) throw new IllegalStateException(); - return EDKeyPair.from128Seed(seedBytes); - } else { - return K256.createKeyPair(seedBytes, account); - } - - } - - public static Seed fromBase58(String b58) { - B58.Decoded decoded = Addresses.decodeSeed(b58); - return new Seed(decoded.version, decoded.payload); - } - - public static Seed fromPassPhrase(String passPhrase) { - return new Seed(passPhraseToSeedBytes(passPhrase)); - } - - public static byte[] passPhraseToSeedBytes(String phrase) { - try { - return new Sha512(phrase.getBytes("utf-8")).finish128(); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - public static IKeyPair getKeyPair(String b58) { - return fromBase58(b58).keyPair(); - } -} - - diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java deleted file mode 100644 index ab61bfec30..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/ECDSASignature.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.ripple.crypto.ecdsa; - -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.ASN1Integer; -import org.bouncycastle.asn1.DERSequenceGenerator; -import org.bouncycastle.asn1.DLSequence; -import org.bouncycastle.crypto.signers.ECDSASigner; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; - -public class ECDSASignature { - /** The two components of the signature. */ - public BigInteger r, s; - - /** Constructs a signature with the given components. */ - public ECDSASignature(BigInteger r, BigInteger s) { - this.r = r; - this.s = s; - } - - public static boolean isStrictlyCanonical(byte[] sig) { - return checkIsCanonical(sig, true); - } - - public static boolean checkIsCanonical(byte[] sig, boolean strict) { - // Make sure signature is canonical - // To protect against signature morphing attacks - - // Signature should be: - // <30> [ <02> ] [ <02> ] - // where - // 6 <= len <= 70 - // 1 <= lenR <= 33 - // 1 <= lenS <= 33 - - int sigLen = sig.length; - - if ((sigLen < 8) || (sigLen > 72)) - return false; - - if ((sig[0] != 0x30) || (sig[1] != (sigLen - 2))) - return false; - - // Find R and check its length - int rPos = 4, rLen = sig[rPos - 1]; - - if ((rLen < 1) || (rLen > 33) || ((rLen + 7) > sigLen)) - return false; - - // Find S and check its length - int sPos = rLen + 6, sLen = sig[sPos - 1]; - if ((sLen < 1) || (sLen > 33) || ((rLen + sLen + 6) != sigLen)) - return false; - - if ((sig[rPos - 2] != 0x02) || (sig[sPos - 2] != 0x02)) - return false; // R or S have wrong type - - if ((sig[rPos] & 0x80) != 0) - return false; // R is negative - - if ((sig[rPos] == 0) && rLen == 1) - return false; // R is zero - - if ((sig[rPos] == 0) && ((sig[rPos + 1] & 0x80) == 0)) - return false; // R is padded - - if ((sig[sPos] & 0x80) != 0) - return false; // S is negative - - if ((sig[sPos] == 0) && sLen == 1) - return false; // S is zero - - if ((sig[sPos] == 0) && ((sig[sPos + 1] & 0x80) == 0)) - return false; // S is padded - - - byte[] rBytes = new byte[rLen]; - byte[] sBytes = new byte[sLen]; - - System.arraycopy(sig, rPos, rBytes, 0, rLen); - System.arraycopy(sig, sPos, sBytes, 0, sLen); - - BigInteger r = new BigInteger(1, rBytes), s = new BigInteger(1, sBytes); - - BigInteger order = SECP256K1.order(); - - if (r.compareTo(order) != -1 || s.compareTo(order) != -1) { - return false; // R or S greater than modulus - } - if (strict) { - return order.subtract(s).compareTo(s) != -1; - } else { - return true; - } - - } - - public static ECDSASignature createSignature(byte[] hash, ECDSASigner signer) { - BigInteger[] sigs = signer.generateSignature(hash); - BigInteger r = sigs[0], s = sigs[1]; - - BigInteger otherS = SECP256K1.order().subtract(s); - if (s.compareTo(otherS) > 0) { - s = otherS; - } - - return new ECDSASignature(r, s); - } - - /** - * DER is an international standard for serializing data structures which is widely used in cryptography. - * It's somewhat like protocol buffers but less convenient. This method returns a standard DER encoding - * of the signature, as recognized by OpenSSL and other libraries. - */ - public byte[] encodeToDER() { - try { - return derByteStream().toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); // Cannot happen. - } - } - - public static ECDSASignature decodeFromDER(byte[] bytes) { - try { - ASN1InputStream decoder = new ASN1InputStream(bytes); - DLSequence seq = (DLSequence) decoder.readObject(); - ASN1Integer r, s; - try { - r = (ASN1Integer) seq.getObjectAt(0); - s = (ASN1Integer) seq.getObjectAt(1); - } catch (ClassCastException e) { - return null; - } finally { - decoder.close(); - } - // OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be - // Thus, we always use the positive versions. See: http://r6.ca/blog/20111119T211504Z.html - return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected ByteArrayOutputStream derByteStream() throws IOException { - // Usually 70-72 bytes. - ByteArrayOutputStream bos = new ByteArrayOutputStream(72); - DERSequenceGenerator seq = new DERSequenceGenerator(bos); - seq.addObject(new ASN1Integer(r)); - seq.addObject(new ASN1Integer(s)); - seq.close(); - return bos; - } -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java deleted file mode 100644 index 1f93f23465..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.ripple.crypto.ecdsa; - -import com.ripple.utils.Sha512; -import com.ripple.utils.Utils; -import org.bouncycastle.crypto.signers.ECDSASigner; -import org.bouncycastle.math.ec.ECPoint; - -import java.math.BigInteger; - -public class K256 { - - /** - * @param secretKey secret point on the curve as BigInteger - * @return corresponding public point - */ - public static byte[] getPublic(BigInteger secretKey) { - return SECP256K1.basePointMultipliedBy(secretKey); - } - - /** - * @param secretKey secret point on the curve as BigInteger - * @return corresponding public point - */ - private static ECPoint computePublic(BigInteger secretKey) { - return SECP256K1.basePoint().multiply(secretKey); - } - - /** - * @param privateGen secret point on the curve as BigInteger - * @return the corresponding public key is the public generator - * (aka public root key, master public key). - * return as byte[] for convenience. - */ - private static ECPoint computePublicGenerator(BigInteger privateGen) { - return computePublic(privateGen); - } - - private static BigInteger computePrivateGen(byte[] seedBytes) { - return generateKey(seedBytes, null); - } - - public static byte[] computePublicKey(byte[] publicGenBytes, - int accountNumber) { - ECPoint rootPubPoint = SECP256K1.curve().decodePoint(publicGenBytes); - BigInteger scalar = generateKey(publicGenBytes, accountNumber); - ECPoint point = SECP256K1.basePoint().multiply(scalar); - ECPoint offset = rootPubPoint.add(point); - return offset.getEncoded(true); - } - - private static BigInteger computeSecretKey(BigInteger privateGen, - byte[] publicGenBytes, - int accountNumber) { - return generateKey(publicGenBytes, accountNumber) - .add(privateGen).mod(SECP256K1.order()); - } - - /** - * @param seedBytes - a bytes sequence of arbitrary length which will be hashed - * @param discriminator - nullable optional uint32 to hash - * @return a number between [1, order -1] suitable as a private key - */ - private static BigInteger generateKey(byte[] seedBytes, Integer discriminator) { - BigInteger key = null; - for (long i = 0; i <= 0xFFFFFFFFL; i++) { - Sha512 sha512 = new Sha512().add(seedBytes); - if (discriminator != null) { - sha512.addU32(discriminator); - } - sha512.addU32((int) i); - byte[] keyBytes = sha512.finish256(); - key = Utils.uBigInt(keyBytes); - if (key.compareTo(BigInteger.ZERO) > 0 && - key.compareTo(SECP256K1.order()) < 0) { - break; - } - } - return key; - } - - static ECDSASignature createECDSASignature(byte[] hash, ECDSASigner signer) { - return ECDSASignature.createSignature(hash, signer); - } - - public static K256KeyPair createKeyPair(byte[] seedBytes, int accountNumber) { - @SuppressWarnings("SpellCheckingInspection") - BigInteger priv; - BigInteger privateGen; - // The private generator (aka root private key, master private key) - privateGen = computePrivateGen(seedBytes); - ECPoint publicGen = computePublicGenerator(privateGen); - byte[] pubGenBytes = publicGen.getEncoded(true); - - if (accountNumber == -1) { - // The root keyPair - return new K256KeyPair(privateGen, publicGen, pubGenBytes); - } else { - priv = computeSecretKey(privateGen, pubGenBytes, accountNumber); - ECPoint pub = computePublic(priv); - return new K256KeyPair(priv, pub, null); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java deleted file mode 100644 index e417c9d85c..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256KeyPair.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.ripple.crypto.ecdsa; - -import com.ripple.crypto.keys.IKeyPair; -import com.ripple.utils.HashUtils; -import com.ripple.utils.Utils; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.crypto.params.ECPrivateKeyParameters; -import org.bouncycastle.crypto.signers.ECDSASigner; -import org.bouncycastle.crypto.signers.HMacDSAKCalculator; -import org.bouncycastle.math.ec.ECPoint; - -import java.math.BigInteger; - -public class K256KeyPair extends K256VerifyingKey implements IKeyPair { - private byte[] privateKey; - private ECPrivateKeyParameters privateKeyParameters; - - K256KeyPair(BigInteger privateKey, ECPoint pub, byte[] pubEncoded) { - super(pub, pubEncoded); - this.privateKey = Utils.padTo256(privateKey.toByteArray()); - privateKeyParameters = new ECPrivateKeyParameters(privateKey, - SECP256K1.params()); - } - - @Override - public byte[] privateKey() { - return privateKey; - } - - @Override - public byte[] signMessage(byte[] message) { - byte[] hash = HashUtils.halfSha512(message); - return signHash(hash); - } - - public byte[] signHash(byte[] bytes) { - ECDSASigner signer = newSigner(); - - ECDSASignature sig = K256.createECDSASignature(bytes, signer); - byte[] der = sig.encodeToDER(); - if (!ECDSASignature.isStrictlyCanonical(der)) { - throw new IllegalStateException("Signature is not strictly canonical"); - } - return der; - } - - private ECDSASigner newSigner() { - ECDSASigner signer = new ECDSASigner( - new HMacDSAKCalculator(new SHA256Digest())); - signer.init(true, privateKeyParameters); - return signer; - } - -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java deleted file mode 100644 index 7681c12ef6..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/K256VerifyingKey.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ripple.crypto.ecdsa; - -import com.ripple.crypto.keys.IVerifyingKey; -import com.ripple.encodings.addresses.Addresses; -import com.ripple.utils.HashUtils; -import org.bouncycastle.crypto.params.ECPublicKeyParameters; -import org.bouncycastle.crypto.signers.ECDSASigner; -import org.bouncycastle.math.ec.ECPoint; - -public class K256VerifyingKey implements IVerifyingKey { - private final ECPublicKeyParameters keyParameters; - private final byte[] canonicalPublicKey; - - K256VerifyingKey(ECPoint publicKey, byte[] publicKeyBytes) { - if (publicKeyBytes == null) { - publicKeyBytes = publicKey.getEncoded(true); - } else if (publicKey == null) { - publicKey = SECP256K1.curve().decodePoint(publicKeyBytes); - } - canonicalPublicKey = publicKeyBytes; - keyParameters = new ECPublicKeyParameters( - publicKey, SECP256K1.params()); - } - - private K256VerifyingKey(byte[] pubKeyBytes) { - this(null, pubKeyBytes); - } - - @Override - public byte[] canonicalPubBytes() { - return canonicalPublicKey; - } - - @Override - public boolean verify(byte[] message, byte[] signature) { - byte[] bytes = HashUtils.halfSha512(message); - return verifyHash(bytes, signature); - } - - public boolean verifyHash(byte[] hash, byte[] signature) { - ECDSASigner signer = new ECDSASigner(); - signer.init(false, keyParameters); - ECDSASignature sig = ECDSASignature.decodeFromDER(signature); - return sig != null && signer.verifySignature(hash, sig.r, sig.s); - } - - public static K256VerifyingKey fromNodePublicKey(String node) { - byte[] pub = Addresses.decodeNodePublic(node); - return new K256VerifyingKey(pub); - } - - public static K256VerifyingKey fromCanonicalPubBytes(byte[] bytes) { - return new K256VerifyingKey(bytes); - } -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java b/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java deleted file mode 100644 index 5350a27f75..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ecdsa/SECP256K1.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.ripple.crypto.ecdsa; - -import org.bouncycastle.asn1.sec.SECNamedCurves; -import org.bouncycastle.asn1.x9.X9ECParameters; -import org.bouncycastle.crypto.params.ECDomainParameters; -import org.bouncycastle.math.ec.ECCurve; -import org.bouncycastle.math.ec.ECPoint; - -import java.math.BigInteger; - -public class SECP256K1 { - private static final ECDomainParameters ecParams; - private static final X9ECParameters params; - - static { - - params = SECNamedCurves.getByName("secp256k1"); - ecParams = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); - } - - public static ECDomainParameters params() { - return ecParams; - } - - public static BigInteger order() { - return ecParams.getN(); - } - - - public static ECCurve curve() { - return ecParams.getCurve(); - } - - public static ECPoint basePoint() { - return ecParams.getG(); - } - - static byte[] basePointMultipliedBy(BigInteger secret) { - return basePoint().multiply(secret).getEncoded(true); - } - -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java deleted file mode 100644 index 71da658b0c..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ed25519/ED25519.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ripple.crypto.ed25519; - -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec; -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; - -public class ED25519 { - static final EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable - .getByName("Ed25519"); -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java deleted file mode 100644 index 5d638617c3..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDKeyPair.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.ripple.crypto.ed25519; - -import com.ripple.crypto.keys.IKeyPair; -import com.ripple.utils.HashUtils; -import com.ripple.utils.Utils; -import net.i2p.crypto.eddsa.EdDSAEngine; -import net.i2p.crypto.eddsa.EdDSAPrivateKey; -import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; -import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; - -import java.math.BigInteger; -import java.security.PrivateKey; - -public class EDKeyPair extends EDVerifyingKey implements IKeyPair { - - private final EdDSAPrivateKeySpec keySpec; - - private EDKeyPair(EdDSAPrivateKeySpec keySpec) { - super(new EdDSAPublicKeySpec(keySpec.getA(), ED25519.ed25519), null); - this.keySpec = keySpec; - } - - public static EDKeyPair from256Seed(byte[] seedBytes) { - EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(seedBytes, - ED25519.ed25519); - return new EDKeyPair(keySpec); - } - - public static EDKeyPair from128Seed(byte[] seedBytes) { - assert seedBytes.length == 16; - return from256Seed(HashUtils.halfSha512(seedBytes)); - } - - @Override - public byte[] privateKey() { - return keySpec.geta(); - } - - @Override - public byte[] signMessage(byte[] message) { - try { - EdDSAEngine sgr = new EdDSAEngine(sha512digest()); - PrivateKey sKey = new EdDSAPrivateKey(keySpec); - sgr.initSign(sKey); - sgr.update(message); - return sgr.sign(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java deleted file mode 100644 index e0c9da8d07..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/ed25519/EDVerifyingKey.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.ripple.crypto.ed25519; - -import com.ripple.crypto.keys.IVerifyingKey; -import net.i2p.crypto.eddsa.EdDSAEngine; -import net.i2p.crypto.eddsa.EdDSAPublicKey; -import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; -import org.bouncycastle.util.Arrays; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class EDVerifyingKey implements IVerifyingKey { - private final EdDSAPublicKey publicKey; - private final byte[] canonicalPubBytes; - @SuppressWarnings("FieldCanBeLocal") - private final byte[] ED_PREFIX = {(byte) 0xED}; - - EDVerifyingKey(EdDSAPublicKeySpec spec, byte[] pubBytes) { - if (pubBytes == null) { - pubBytes = spec.getA().toByteArray(); - } else if (spec == null) { - spec = new EdDSAPublicKeySpec(pubBytes, ED25519.ed25519); - } - publicKey = new EdDSAPublicKey(spec); - canonicalPubBytes = Arrays.concatenate(ED_PREFIX, pubBytes); - } - - MessageDigest sha512digest() { - try { - return MessageDigest.getInstance("SHA-512"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - @Override - public byte[] canonicalPubBytes() { - return canonicalPubBytes; - } - - @Override - public boolean verify(byte[] message, byte[] sigBytes) { - try { - EdDSAEngine sgr = new EdDSAEngine(sha512digest()); - sgr.initVerify(publicKey); - sgr.update(message); - return sgr.verify(sigBytes); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static EDVerifyingKey fromCanonicalPubBytes(byte[] bytes) { - // Strip the 0xED prefix from the key - byte[] pubBytes = Arrays.copyOfRange(bytes, 1, bytes.length); - return new EDVerifyingKey(null, pubBytes); - } -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java b/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java deleted file mode 100644 index ab76848154..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/keys/IKeyPair.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.ripple.crypto.keys; - -public interface IKeyPair extends IVerifyingKey { - byte[] privateKey(); - byte[] signMessage(byte[] message); -} diff --git a/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java b/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java deleted file mode 100644 index 1b1c6ed7d0..0000000000 --- a/ripple-core/src/main/java/com/ripple/crypto/keys/IVerifyingKey.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ripple.crypto.keys; - - -import com.ripple.crypto.ecdsa.K256VerifyingKey; -import com.ripple.crypto.ed25519.EDVerifyingKey; -import com.ripple.encodings.common.B16; -import com.ripple.utils.HashUtils; - -public interface IVerifyingKey { - default String canonicalPubHex() { - return B16.encode(canonicalPubBytes()); - } - - default byte[] id() { - return HashUtils.SHA256_RIPEMD160(canonicalPubBytes()); - } - - byte[] canonicalPubBytes(); - - boolean verify(byte[] message, byte[] sigBytes); - - static IVerifyingKey from(byte[] bytes) { - if (bytes[0] == (byte) 0xED) { - return EDVerifyingKey.fromCanonicalPubBytes(bytes); - } else { - return K256VerifyingKey.fromCanonicalPubBytes(bytes); - } - } -} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java b/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java deleted file mode 100644 index 5d8022a9b6..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/addresses/Addresses.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ripple.encodings.addresses; - - -import com.ripple.encodings.base58.B58; -import com.ripple.encodings.basex.EncodingFormatException; -import com.ripple.encodings.basex.IBaseX; -import org.omg.IOP.Encoding; - -public class Addresses { - public static final B58 codec = new B58("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); - - // Otherwise known as `family seed` - public static final B58.Version SEED_K256 = new B58.Version( - 33, "seedK256", 16); - - public static final B58.Version SEED_ED25519 = new B58.Version( - "01E14B", "seedEd25519", 16); - - public static final B58.Version ACCOUNT_ID = new B58.Version( - 0, "accountId", 20); - - public static final B58.Version NODE_PUBLIC_KEY = new B58.Version( - 28, "nodePublicKey", 33); - - public static final B58.Version NODE_PRIVATE_KEY = new B58.Version( - 33, "nodePrivateKey", 32); - - public static byte[] decode(String encoded, B58.Version version) { - return codec.decodeVersioned(encoded, version).payload; - } - - public static String encode(byte[] bytes, B58.Version version) { - return codec.encodeVersioned(bytes, version); - } - - public static byte[] decodeSeedToBytes(String seed) { - return codec.decodeVersioned(seed, SEED_K256, SEED_ED25519) - .payload; - } - - public static B58.Decoded decodeSeed(String seed) { - return codec.decodeVersioned(seed, SEED_K256, SEED_ED25519); - } - - public static String encodeSeedK256(byte[] bytes) { - return encode(bytes, SEED_K256); - } - - public static String encodeAccountID(byte[] bytes) { - return encode(bytes, ACCOUNT_ID); - } - - public static byte[] decodeAccountID(String id) { - return decode(id, ACCOUNT_ID); - } - - public static String encodeNodePublic(byte[] bytes) { - return encode(bytes, NODE_PUBLIC_KEY); - } - - public static byte[] decodeNodePublic(String base58) { - return decode(base58, NODE_PUBLIC_KEY); - } - - public static boolean isValid(String encoded, B58.Version... versions) { - try { - codec.decodeVersioned(encoded, versions); - return true; - } catch (EncodingFormatException e) { - return false; - } - } - - public static boolean isValidAccountID(String encoded) { - return isValid(encoded, ACCOUNT_ID); - } -} diff --git a/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java b/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java deleted file mode 100644 index a6b928824e..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/base58/B58.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.ripple.encodings.base58; - -import com.ripple.encodings.basex.BaseX; - -public class B58 extends BaseX { - public B58(String alphabet) { - super(alphabet); - } -} diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java b/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java deleted file mode 100644 index 4ebbfc871a..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/basex/BaseX.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.ripple.encodings.basex; - -import com.ripple.utils.HashUtils; - -import java.util.Arrays; - -public class BaseX implements IBaseX { - private char[] alphabet; - private final char encodedZero; - protected final int[] indexes; - - public BaseX(String alphabet_) { - if (alphabet_.length() > 256) { - throw new IllegalArgumentException(); - } - alphabet = alphabet_.toCharArray(); - indexes = new int[128]; - encodedZero = alphabet[0]; - Arrays.fill(indexes, -1); - for (int i = 0; i < alphabet.length; i++) { - indexes[alphabet[i]] = i; - } - } - - private static String repeat(int times, char repeated) { - char[] chars = new char[times]; - Arrays.fill(chars, repeated); - return new String(chars); - } - - /** - * Encodes the given bytes as a base58 string (no checksum is appended). - * - * @param input the bytes to encode - * @return the base58-encoded string - */ - @Override - public String encode(byte[] input) { - if (input.length == 0) { - return ""; - } - // Count leading zeros. - int zeros = 0; - while (zeros < input.length && input[zeros] == 0) { - ++zeros; - } - // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) - input = Arrays.copyOf(input, input.length); // since we modify it in-place - char[] encoded = new char[input.length * 2]; // upper bound - int outputStart = encoded.length; - for (int inputStart = zeros; inputStart < input.length; ) { - encoded[--outputStart] = alphabet[divmod(input, inputStart, 256, 58)]; - if (input[inputStart] == 0) { - ++inputStart; // optimization - skip leading zeros - } - } - // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. - while (outputStart < encoded.length && encoded[outputStart] == encodedZero) { - ++outputStart; - } - while (--zeros >= 0) { - encoded[--outputStart] = encodedZero; - } - // Return encoded string (including encoded leading zeros). - return new String(encoded, outputStart, encoded.length - outputStart); - } - - /** - * Decodes the given base58 string into the original data bytes. - * - * @param input the base58-encoded string to decode - * @return the decoded data bytes - * @throws EncodingFormatException if the given string is not a valid base58 string - */ - @Override - public byte[] decode(String input) throws EncodingFormatException { - if (input.length() == 0) { - return new byte[0]; - } - // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). - byte[] input58 = new byte[input.length()]; - for (int i = 0; i < input.length(); ++i) { - char c = input.charAt(i); - int digit = c < 128 ? indexes[c] : -1; - if (digit < 0) { - throw new EncodingFormatException("Illegal character " + c + " at position " + i); - } - input58[i] = (byte) digit; - } - // Count leading zeros. - int zeros = 0; - while (zeros < input58.length && input58[zeros] == 0) { - ++zeros; - } - // Convert base-58 digits to base-256 digits. - byte[] decoded = new byte[input.length()]; - int outputStart = decoded.length; - for (int inputStart = zeros; inputStart < input58.length; ) { - decoded[--outputStart] = divmod(input58, inputStart, 58, 256); - if (input58[inputStart] == 0) { - ++inputStart; // optimization - skip leading zeros - } - } - // Ignore extra leading zeroes that were added during the calculation. - while (outputStart < decoded.length && decoded[outputStart] == 0) { - ++outputStart; - } - // Return decoded data (including original number of leading zeros). - return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); - } - - /** - * Decodes the given base58 string into the original data bytes, using the checksum in the - * last 4 bytes of the decoded data to verify that the rest are correct. The checksum is - * removed from the returned data. - * - * @param input the base58-encoded string to decode (which should include the checksum) - * @throws EncodingFormatException if the input is not base 58 or the checksum does not validate. - */ - public byte[] decodeChecked(String input) throws EncodingFormatException { - byte[] decoded = decode(input); - if (decoded.length < 4) - throw new EncodingFormatException("Input too short"); - byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4); - byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length); - byte[] actualChecksum = Arrays.copyOfRange(HashUtils.doubleDigest(data), 0, 4); - if (!Arrays.equals(checksum, actualChecksum)) - throw new EncodingFormatException("Checksum does not validate"); - return data; - } - - /** - * Divides a number, represented as an array of bytes each containing a single digit - * in the specified base, by the given divisor. The given number is modified in-place - * to contain the quotient, and the return value is the remainder. - * - * @param number the number to divide - * @param firstDigit the index within the array of the first non-zero digit - * (this is used for optimization by skipping the leading zeros) - * @param base the base in which the number's digits are represented (up to 256) - * @param divisor the number to divide by (up to 256) - * @return the remainder of the division operation - */ - private byte divmod(byte[] number, int firstDigit, int base, int divisor) { - // this is just long division which accounts for the base of the input digits - int remainder = 0; - for (int i = firstDigit; i < number.length; i++) { - int digit = (int) number[i] & 0xFF; - int temp = remainder * base + digit; - number[i] = (byte) (temp / divisor); - remainder = temp % divisor; - } - return (byte) remainder; - } - - @Override - public byte[] findPrefix(int payLoadLength, String desiredPrefix) { - if (alphabet.length != 58) { - throw new IllegalStateException("Must be base58"); - } - int totalLength = payLoadLength + 4; // for the checksum - double chars = Math.log(Math.pow(256, totalLength)) / Math.log(58); - int requiredChars = (int) Math.ceil(chars + 0.2D); - // Mess with this to see stability tests fail - int charPos = (alphabet.length / 2) - 1; - char padding = alphabet[(charPos)]; - String template = desiredPrefix + repeat(requiredChars, padding); - byte[] decoded = decode(template); - return copyOfRange(decoded, 0, decoded.length - totalLength); - } - - @Override - public String encodeVersioned(byte[] input, Version version) { - if (input.length != version.expectedLength) { - throw new IllegalArgumentException( - "input length=" + input.length + - ", expected=" + version.expectedLength); - } - return encode(concatVersionAndAddChecksum(input, version.bytes)); - } - - private byte[] concatVersionAndAddChecksum(byte[] input, byte[] version) { - byte[] buffer = new byte[input.length + version.length]; - System.arraycopy(version, 0, buffer, 0, version.length); - System.arraycopy(input, 0, buffer, version.length, input.length); - byte[] checkSum = copyOfRange(HashUtils.doubleDigest(buffer), 0, 4); - byte[] output = new byte[buffer.length + checkSum.length]; - System.arraycopy(buffer, 0, output, 0, buffer.length); - System.arraycopy(checkSum, 0, output, buffer.length, checkSum.length); - return output; - } - - public Decoded decodeVersioned(String input, - Version... possibleVersions) throws EncodingFormatException { - - byte[] buffer = decodeChecked(input); - - Version foundVersion = null; - int expectedLength = possibleVersions[0].expectedLength; - int versionLength = buffer.length - expectedLength; - byte[] versionBytes = copyOfRange(buffer, 0, versionLength); - - for (Version possible : possibleVersions) { - if (possible.expectedLength != expectedLength) { - throw new IllegalStateException(); - } - - if (Arrays.equals(possible.bytes, versionBytes)) { - foundVersion = possible; - break; - } - } - if (foundVersion == null) { - throw new EncodingFormatException("Incorrect version"); - } - - byte[] bytes = copyOfRange(buffer, versionLength, buffer.length); - if (bytes.length != expectedLength) { - throw new EncodingFormatException("Incorrect length"); - } - - return new Decoded(foundVersion, bytes); - } - - private byte[] copyOfRange(byte[] source, int from, int to) { - byte[] range = new byte[to - from]; - System.arraycopy(source, from, range, 0, range.length); - return range; - } - -} \ No newline at end of file diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java b/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java deleted file mode 100644 index 4c56ffa1e9..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/basex/EncodingFormatException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ripple.encodings.basex; - -public class EncodingFormatException extends RuntimeException{ - public EncodingFormatException(String message) { - super(message); - } -} diff --git a/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java b/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java deleted file mode 100644 index 84d98aa51b..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/basex/IBaseX.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ripple.encodings.basex; - -import com.ripple.encodings.common.B16; - -public interface IBaseX { - String encode(byte[] input); - byte[] decode(String input); - - byte[] findPrefix(int payLoadLength, String desiredPrefix); - - String encodeVersioned(byte[] input, Version version); - Decoded decodeVersioned(String input, Version... possibleVersions); - - class Decoded { - public final Version version; - public final byte[] payload; - - Decoded(Version version, byte[] payload) { - this.version = version; - this.payload = payload; - } - } - - class Version { - public final byte[] bytes; - public final String name; - public final int expectedLength; - - public Version(byte[] bytes, String name, int length) { - this.bytes = bytes; - this.name = name; - this.expectedLength = length; - } - public Version(int aByte, String name, int length) { - this(new byte[]{(byte) aByte}, name, length); - } - public Version(String hex, String name, int length) { - this(B16.decode(hex), name, length); - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/encodings/common/B16.java b/ripple-core/src/main/java/com/ripple/encodings/common/B16.java deleted file mode 100644 index 9ab895721c..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/common/B16.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ripple.encodings.common; - - -import static org.bouncycastle.util.encoders.Hex.toHexString; - -public class B16 { - public static String toStringTrimmed(byte[] bytes) { - int offset = 0; - if (bytes[0] == 0) { - offset = 1; - } - return toHexString(bytes, offset, bytes.length - offset).toUpperCase(); - } - public static String encode(byte[] bytes) { - return toHexString(bytes).toUpperCase(); - } - public static byte[] decode(String hex) { - return org.bouncycastle.util.encoders.Hex.decode(hex); - } -} diff --git a/ripple-core/src/main/java/com/ripple/encodings/common/B64.java b/ripple-core/src/main/java/com/ripple/encodings/common/B64.java deleted file mode 100644 index e48b7d1a70..0000000000 --- a/ripple-core/src/main/java/com/ripple/encodings/common/B64.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.ripple.encodings.common; - -import org.bouncycastle.util.encoders.Base64; - -public class B64 { - public static String toString(byte[] bytes) { - return Base64.toBase64String(bytes); - } - public static byte[] decode(String string) { - return Base64.decode(string); - } -} diff --git a/ripple-core/src/main/java/com/ripple/utils/HashUtils.java b/ripple-core/src/main/java/com/ripple/utils/HashUtils.java deleted file mode 100644 index 2d79986957..0000000000 --- a/ripple-core/src/main/java/com/ripple/utils/HashUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ripple.utils; - -import org.bouncycastle.crypto.digests.RIPEMD160Digest; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class HashUtils { - private static final MessageDigest digest; - static { - try { - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); // Can't happen. - } - } - - /** - * See {@link HashUtils#doubleDigest(byte[], int, int)}. - */ - public static byte[] doubleDigest(byte[] input) { - return doubleDigest(input, 0, input.length); - } - - /** - * Calculates the SHA-256 hash of the given byte range, and then hashes the resulting hash again. This is - * standard procedure in Bitcoin. The resulting hash is in big endian form. - */ - public static byte[] doubleDigest(byte[] input, int offset, int length) { - synchronized (digest) { - digest.reset(); - digest.update(input, offset, length); - byte[] first = digest.digest(); - return digest.digest(first); - } - } - - public static byte[] halfSha512(byte[] bytes) { - return new Sha512(bytes).finish256(); - } - - public static byte[] quarterSha512(byte[] bytes) { - return new Sha512(bytes).finish128(); - } - - public static byte[] sha512(byte[] bytes) { - return new Sha512(bytes).finish(); - } - - public static byte[] SHA256_RIPEMD160(byte[] input) { - try { - byte[] sha256 = MessageDigest.getInstance("SHA-256").digest(input); - RIPEMD160Digest digest = new RIPEMD160Digest(); - digest.update(sha256, 0, sha256.length); - byte[] out = new byte[20]; - digest.doFinal(out, 0); - return out; - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); // Cannot happen. - } - } -} diff --git a/ripple-core/src/main/java/com/ripple/utils/Sha512.java b/ripple-core/src/main/java/com/ripple/utils/Sha512.java deleted file mode 100644 index bafd20b134..0000000000 --- a/ripple-core/src/main/java/com/ripple/utils/Sha512.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.ripple.utils; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; - -public class Sha512 { - private MessageDigest messageDigest; - - public Sha512() { - try { - messageDigest = MessageDigest.getInstance("SHA-512"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - public Sha512(byte[] start) { - this(); - add(start); - } - - public Sha512 add(byte[] bytes) { - messageDigest.update(bytes); - return this; - } - - public Sha512 addU32(int i) { - messageDigest.update((byte) ((i >>> 24) & 0xFF)); - messageDigest.update((byte) ((i >>> 16) & 0xFF)); - messageDigest.update((byte) ((i >>> 8) & 0xFF)); - messageDigest.update((byte) ((i) & 0xFF)); - return this; - } - - private byte[] finishTaking(int size) { - byte[] hash = new byte[size]; - System.arraycopy(messageDigest.digest(), 0, hash, 0, size); - return hash; - } - - public byte[] finish128() { - return finishTaking(16); - } - - public byte[] finish256() { - return finishTaking(32); - } - - public byte[] finish() { - return messageDigest.digest(); - } -} diff --git a/ripple-core/src/main/java/com/ripple/utils/Utils.java b/ripple-core/src/main/java/com/ripple/utils/Utils.java deleted file mode 100644 index 8376f1637f..0000000000 --- a/ripple-core/src/main/java/com/ripple/utils/Utils.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.ripple.utils; - -import com.ripple.encodings.common.B16; - -import java.math.BigInteger; -import java.util.Arrays; - -public class Utils { - public static String bigHex(BigInteger bn) { - return B16.toStringTrimmed(bn.toByteArray()); - } - - public static BigInteger uBigInt(byte[] bytes) { - return new BigInteger(1, bytes); - } - - public static byte[] leadingZeroesTrimmedOrPaddedTo(int size, byte[] bytes) { - if (bytes.length == size) { - return bytes; - } - if (bytes.length > size) { - int length = bytes.length; - int offset = 0; - while (length > size && bytes[offset++] == 0) { - length--; - } - if (length > size) { - throw new IllegalArgumentException( - "bytes.length: " + bytes.length + " > " + - size); - } - return copyFrom(bytes, offset, size); - } - - return padTo(bytes, size); - } - - public static byte[] padTo256(byte[] bytes) { - return leadingZeroesTrimmedOrPaddedTo(32, bytes); - } - - public static byte[] padTo160(byte[] bytes) { - return leadingZeroesTrimmedOrPaddedTo(20, bytes); - } - - private static byte[] copyFrom(byte[] bytes, int offset, int size) { - byte[] result = new byte[size]; - System.arraycopy(bytes, offset, result, 0, size); - return result; - } - - private static byte[] padTo(byte[] bytes, int size) { - byte[] result = new byte[size]; - int offset = result.length - bytes.length; - System.arraycopy(bytes, 0, result, offset, bytes.length); - return result; - } -} diff --git a/settings.gradle b/settings.gradle index 7c7add5bef..27d8397e5d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core' +include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core-0.0.1' From 8cf838223f03b93c6ebbefa4b7c51131ca42b74c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Apr 2019 13:08:55 +0300 Subject: [PATCH 13/28] Updated on 2026-08-14 --- ripple-core-0.0.1/build.gradle | 54 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/ripple-core-0.0.1/build.gradle b/ripple-core-0.0.1/build.gradle index 31be8312e1..7ee498ed2c 100644 --- a/ripple-core-0.0.1/build.gradle +++ b/ripple-core-0.0.1/build.gradle @@ -1,2 +1,52 @@ -configurations.maybeCreate("default") -artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) \ No newline at end of file +apply plugin: 'java' +apply plugin: 'kotlin' + +description = 'ripple-core' + +version = '0.0.1-SNAPSHOT' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +dependencies { + compile 'net.i2p.crypto:eddsa:0.2.0' + compile 'org.bouncycastle:bcprov-jdk15on:1.58' + compile 'org.json:json:20171018' + compile 'com.fasterxml.jackson.core:jackson-databind:2.9.3' + testCompile 'junit:junit:4.12' + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5" +} +buildscript { + ext.kotlin_version = '1.3.0' + repositories { + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +repositories { + mavenCentral() +} +compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} +compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} + +task getDeps(type: Copy) { + from configurations.compile + into "$rootDir/jars/" +} + +kotlin { + experimental { + coroutines "enable" + } +} \ No newline at end of file From 300b38450edc2c8225088d4ee90773a9dde6fb08 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Apr 2019 15:17:05 +0300 Subject: [PATCH 14/28] Updated on 2026-08-14 --- .idea/gradle.xml | 2 +- app/build.gradle | 9 ++- .../tangem/domain/wallet/xrp/XrpPayment.java | 1 + ripple-core-0.0.1/build.gradle | 53 +++--------------- ripple-core/build.gradle | 2 + ripple-core/ripple-core-0.0.1-SNAPSHOT.jar | Bin 0 -> 294113 bytes settings.gradle | 2 +- 7 files changed, 21 insertions(+), 48 deletions(-) create mode 100644 ripple-core/build.gradle create mode 100644 ripple-core/ripple-core-0.0.1-SNAPSHOT.jar diff --git a/.idea/gradle.xml b/.idea/gradle.xml index da117a274a..dbe604a60c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -11,7 +11,7 @@ diff --git a/app/build.gradle b/app/build.gradle index dff789a723..81e51cffcf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,7 +47,14 @@ dependencies { implementation project(':card-common') implementation project(':card-android') implementation project(':server-android') - implementation project(':ripple-core-0.0.1') + implementation project(':ripple-core') + + //for ripple-core TODO: move to ripple-core? + implementation 'net.i2p.crypto:eddsa:0.2.0' + implementation 'org.bouncycastle:bcprov-jdk15on:1.58' + //noinspection DuplicatePlatformClasses + implementation 'org.json:json:20171018' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' // implementation 'com.github.TangemCash:card-common:0.1.2' // implementation 'com.github.TangemCash:card-android:0.1.3' diff --git a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java index 1d202c922f..449d755e65 100644 --- a/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java +++ b/app/src/main/java/com/tangem/domain/wallet/xrp/XrpPayment.java @@ -1,5 +1,6 @@ package com.tangem.domain.wallet.xrp; + import com.ripple.core.types.known.tx.txns.Payment; public class XrpPayment extends Payment { diff --git a/ripple-core-0.0.1/build.gradle b/ripple-core-0.0.1/build.gradle index 7ee498ed2c..ff793da726 100644 --- a/ripple-core-0.0.1/build.gradle +++ b/ripple-core-0.0.1/build.gradle @@ -1,52 +1,15 @@ -apply plugin: 'java' -apply plugin: 'kotlin' +configurations.maybeCreate("default") +artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) -description = 'ripple-core' - -version = '0.0.1-SNAPSHOT' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +apply plugin: 'java-library' +apply plugin: 'com.github.dcendents.android-maven' dependencies { - compile 'net.i2p.crypto:eddsa:0.2.0' - compile 'org.bouncycastle:bcprov-jdk15on:1.58' - compile 'org.json:json:20171018' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.3' - testCompile 'junit:junit:4.12' - testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5" -} -buildscript { - ext.kotlin_version = '1.3.0' - repositories { - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } + implementation 'net.i2p.crypto:eddsa:0.2.0' + implementation 'org.bouncycastle:bcprov-jdk15on:1.58' + implementation 'org.json:json:20171018' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' } repositories { mavenCentral() -} -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -task getDeps(type: Copy) { - from configurations.compile - into "$rootDir/jars/" -} - -kotlin { - experimental { - coroutines "enable" - } } \ No newline at end of file diff --git a/ripple-core/build.gradle b/ripple-core/build.gradle new file mode 100644 index 0000000000..31be8312e1 --- /dev/null +++ b/ripple-core/build.gradle @@ -0,0 +1,2 @@ +configurations.maybeCreate("default") +artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) \ No newline at end of file diff --git a/ripple-core/ripple-core-0.0.1-SNAPSHOT.jar b/ripple-core/ripple-core-0.0.1-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..0600aabbdbdf9d9af603a1a0e36a8b640acad177 GIT binary patch literal 294113 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∈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 literal 0 HcmV?d00001 diff --git a/settings.gradle b/settings.gradle index 27d8397e5d..7c7add5bef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core-0.0.1' +include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core' From 39de788b0310cfc8c63e1f0ddf537d046054b392 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Apr 2019 19:36:37 +0300 Subject: [PATCH 15/28] Updated on 2026-08-14 --- .idea/gradle.xml | 1 - app/build.gradle | 24 ++++++++---------- ripple-core-0.0.1/build.gradle | 15 ----------- .../ripple-core-0.0.1-SNAPSHOT.jar | Bin 294113 -> 0 bytes ripple-core/build.gradle | 2 -- ripple-core/ripple-core-0.0.1-SNAPSHOT.jar | Bin 294113 -> 0 bytes settings.gradle | 2 +- 7 files changed, 12 insertions(+), 32 deletions(-) delete mode 100644 ripple-core-0.0.1/build.gradle delete mode 100644 ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar delete mode 100644 ripple-core/build.gradle delete mode 100644 ripple-core/ripple-core-0.0.1-SNAPSHOT.jar diff --git a/.idea/gradle.xml b/.idea/gradle.xml index dbe604a60c..1dde4f60b5 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -11,7 +11,6 @@ diff --git a/app/build.gradle b/app/build.gradle index 81e51cffcf..7e1262e58b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,19 +47,9 @@ dependencies { implementation project(':card-common') implementation project(':card-android') implementation project(':server-android') - implementation project(':ripple-core') - - //for ripple-core TODO: move to ripple-core? - implementation 'net.i2p.crypto:eddsa:0.2.0' - implementation 'org.bouncycastle:bcprov-jdk15on:1.58' - //noinspection DuplicatePlatformClasses - implementation 'org.json:json:20171018' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' - -// implementation 'com.github.TangemCash:card-common:0.1.2' -// implementation 'com.github.TangemCash:card-android:0.1.3' -// implementation 'com.github.TangemCash:server-android:0.1.4' - + // implementation 'com.github.TangemCash:card-common:0.1.2' + // implementation 'com.github.TangemCash:card-android:0.1.3' + // implementation 'com.github.TangemCash:server-android:0.1.4' implementation 'androidx.appcompat:appcompat:1.1.0-alpha01' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' @@ -89,4 +79,12 @@ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.2.0' implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0' + + implementation files('libs/ripple-core-0.0.1.jar') + //4 dependencies for ripple-core TODO: move to module? + implementation 'net.i2p.crypto:eddsa:0.2.0' + implementation 'org.bouncycastle:bcprov-jdk15on:1.58' + //noinspection DuplicatePlatformClasses + implementation 'org.json:json:20171018' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' } \ No newline at end of file diff --git a/ripple-core-0.0.1/build.gradle b/ripple-core-0.0.1/build.gradle deleted file mode 100644 index ff793da726..0000000000 --- a/ripple-core-0.0.1/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -configurations.maybeCreate("default") -artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) - -apply plugin: 'java-library' -apply plugin: 'com.github.dcendents.android-maven' - -dependencies { - implementation 'net.i2p.crypto:eddsa:0.2.0' - implementation 'org.bouncycastle:bcprov-jdk15on:1.58' - implementation 'org.json:json:20171018' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' -} -repositories { - mavenCentral() -} \ No newline at end of file diff --git a/ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar b/ripple-core-0.0.1/ripple-core-0.0.1-SNAPSHOT.jar deleted file mode 100644 index 0600aabbdbdf9d9af603a1a0e36a8b640acad177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294113 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∈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 diff --git a/ripple-core/build.gradle b/ripple-core/build.gradle deleted file mode 100644 index 31be8312e1..0000000000 --- a/ripple-core/build.gradle +++ /dev/null @@ -1,2 +0,0 @@ -configurations.maybeCreate("default") -artifacts.add("default", file('ripple-core-0.0.1-SNAPSHOT.jar')) \ No newline at end of file diff --git a/ripple-core/ripple-core-0.0.1-SNAPSHOT.jar b/ripple-core/ripple-core-0.0.1-SNAPSHOT.jar deleted file mode 100644 index 0600aabbdbdf9d9af603a1a0e36a8b640acad177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294113 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∈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 diff --git a/settings.gradle b/settings.gradle index 7c7add5bef..ac821b1c6c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':card-android', ':server-android', ':card-common', ':ripple-core' +include ':app', ':card-android', ':server-android', ':card-common' From 652c47d2eb08e0d397906cc8cbe46762b0b792f3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Apr 2019 12:15:45 +0300 Subject: [PATCH 16/28] Updated on 2026-08-14 --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7e1262e58b..7151fdcba5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -82,9 +82,9 @@ dependencies { implementation files('libs/ripple-core-0.0.1.jar') //4 dependencies for ripple-core TODO: move to module? - implementation 'net.i2p.crypto:eddsa:0.2.0' + implementation 'net.i2p.crypto:eddsa:0.3.0' implementation 'org.bouncycastle:bcprov-jdk15on:1.58' //noinspection DuplicatePlatformClasses - implementation 'org.json:json:20171018' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.3' + implementation 'org.json:json:20180813' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' } \ No newline at end of file From 348942a62ac57af6ee4d30226dbba65fb19a3166 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Apr 2019 16:29:33 +0300 Subject: [PATCH 17/28] Updated on 2026-08-14 --- .../tangem/server_android/data/LocalStorage.kt | 6 +++++- .../src/main/res/drawable/card_ru037.png | Bin 0 -> 110030 bytes .../src/main/res/drawable/card_ru039.png | Bin 0 -> 114903 bytes 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 server-android/src/main/res/drawable/card_ru037.png create mode 100644 server-android/src/main/res/drawable/card_ru039.png diff --git a/server-android/src/main/java/com/tangem/server_android/data/LocalStorage.kt b/server-android/src/main/java/com/tangem/server_android/data/LocalStorage.kt index eeed2c053e..f7a1d91c9a 100644 --- a/server-android/src/main/java/com/tangem/server_android/data/LocalStorage.kt +++ b/server-android/src/main/java/com/tangem/server_android/data/LocalStorage.kt @@ -49,7 +49,7 @@ class LocalStorage artworks = HashMap() } - if (artworks.count() < 21) { + if (artworks.count() < 23) { // forceSave=true only on the last one putResourceArtworkToCatalog(R.drawable.card_default, false) putResourceArtworkToCatalog(R.drawable.card_default_nft, false) @@ -71,6 +71,8 @@ class LocalStorage putResourceArtworkToCatalog(R.drawable.card_ru030, false) putResourceArtworkToCatalog(R.drawable.card_ru031, false) putResourceArtworkToCatalog(R.drawable.card_ru032, false) + putResourceArtworkToCatalog(R.drawable.card_ru037, false) + putResourceArtworkToCatalog(R.drawable.card_ru039, false) putResourceArtworkToCatalog(R.drawable.card_ff32, true) } if (batchesFile.exists()) { @@ -244,6 +246,8 @@ class LocalStorage card.batch == "0020" -> R.drawable.card_ru030 card.batch == "0021" -> R.drawable.card_ru031 card.batch == "0022" -> R.drawable.card_ru032 + card.batch == "0025" -> R.drawable.card_ru037 + card.batch == "0026" -> R.drawable.card_ru039 card.batch == "FF32" -> R.drawable.card_ff32 else -> null diff --git a/server-android/src/main/res/drawable/card_ru037.png b/server-android/src/main/res/drawable/card_ru037.png new file mode 100644 index 0000000000000000000000000000000000000000..362fbca5b96e7ce0203e8bfcd31f6b219bad18d5 GIT binary patch literal 110030 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%0D*2(hl+(EL>-6-lwx@4~EXRt~ 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 literal 0 HcmV?d00001 diff --git a/server-android/src/main/res/drawable/card_ru039.png b/server-android/src/main/res/drawable/card_ru039.png new file mode 100644 index 0000000000000000000000000000000000000000..a508efef6c2a739917b8e97ddd76708e3a67a425 GIT binary patch literal 114903 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

}JxpG12D!%7b<+*n*o5ad~Zd17C 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
I?uiK@Rc%zQn==*grf*uQ7egE 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 literal 0 HcmV?d00001 From e607d78c499d307eae2e35d948645cb9ed1a4533 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Apr 2019 18:36:32 +0300 Subject: [PATCH 18/28] Updated on 2026-08-14 --- .../com/tangem/domain/wallet/cardano/CardanoEngine.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java index 901d4bcfef..9a12b2ab4e 100644 --- a/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/cardano/CardanoEngine.java @@ -667,7 +667,7 @@ public class CardanoEngine extends CoinEngine { blockchainRequestsCallbacks.onComplete(!ctx.hasError()); } else { blockchainRequestsCallbacks.onProgress(); - Log.e(TAG, "FAIL INSIGHT_UNSPENT_OUTPUTS Exception"); + Log.e(TAG, "FAIL ADALITE_UNSPENT_OUTPUTS Exception"); } } @@ -675,17 +675,14 @@ public class CardanoEngine extends CoinEngine { public void onSuccess(String method, List listResponse) { Log.e(TAG, "Wrong response type for requestBalanceAndUnspentTransactions"); ctx.setError("Wrong response type for requestBalanceAndUnspentTransactions"); + blockchainRequestsCallbacks.onComplete(false); } @Override public void onFail(String method, String message) { Log.i(TAG, "onFail: " + method + " " + message); ctx.setError(message); - if (serverApiAdalite.isRequestsSequenceCompleted()) { - blockchainRequestsCallbacks.onComplete(false); - } else { - blockchainRequestsCallbacks.onProgress(); - } + blockchainRequestsCallbacks.onComplete(false); } }; From 5f95395ff25b9b8882424b19c6f50a440010c1e9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Apr 2019 18:52:53 +0300 Subject: [PATCH 19/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BitcoinNode.kt | 38 +++++++------------ .../tangem/domain/wallet/ltc/LitecoinNode.kt | 4 +- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt index 2b1e170b29..d36b1b0789 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt @@ -1,29 +1,17 @@ package com.tangem.domain.wallet.btc enum class BitcoinNode(val host: String, val port: Int, val proto: String) { - N_001("electrum.anduck.net", 50001, "tcp"), - N_002("electrum.qtornado.com", 50001, "tcp"), - N_003("e-x.not.fyi", 50001, "tcp"), - N_004("electrum.vom-stausee.de", 50001, "tcp"), - N_005("electrum2.eff.ro", 50001, "tcp"), - N_006("electrum.coinucopia.io", 50001, "tcp"), - N_007("electrum.coinop.cc", 50002, "ssl"), - N_008("electrum.vom-stausee.de", 50002, "ssl"), - N_009("dedi.jochen-hoenicke.de", 50002, "ssl"), - N_010("e-x.not.fyi", 50002, "ssl"), - N_011("electrum.villocq.com", 50002, "ssl"), - N_012("electrum.anduck.net", 50012, "ssl"), - N_013("technetium.network", 50002, "ssl"), - N_014("electrum.coinucopia.io", 50002, "ssl"), - N_015("dimon.trimon.de", 50002, "ssl"), - N_016("btc.gravitech.net", 50002, "ssl"), - N_017("fn.48.org", 50002, "ssl"), - N_018("vps.hsmiths.com", 50002, "ssl"), - N_019("electrum.qtornado.com", 50002, "ssl"), - N_020("electrum-server.ninja", 50002, "ssl"), - N_021("electrum2.eff.ro", 50002, "ssl"), - N_022("electrum.hsmiths.com", 995, "ssl"), - N_023("electrum.hsmiths.com", 50002, "ssl"), - N_024("139.162.14.142", 50002, "ssl"), - N_025("tardis.bauerj.eu", 50002, "ssl"), + N_001("electrum.coinop.cc", 50002, "ssl"), + N_002("dedi.jochen-hoenicke.de", 50002, "ssl"), + N_003("technetium.network", 50002, "ssl"), + N_004("electrum.coinucopia.io", 50002, "ssl"), + N_005("dimon.trimon.de", 50002, "ssl"), + N_006("btc.gravitech.net", 50002, "ssl"), + N_007("fn.48.org", 50002, "ssl"), + N_008("vps.hsmiths.com", 50002, "ssl"), + N_009("electrum.qtornado.com", 50002, "ssl"), + N_010("electrum2.eff.ro", 50002, "ssl"), + N_011("electrum.hsmiths.com", 995, "ssl"), + N_012("electrum.hsmiths.com", 50002, "ssl"), + N_013("tardis.bauerj.eu", 50002, "ssl"), } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt index 12d59de976..fce1899f72 100644 --- a/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/ltc/LitecoinNode.kt @@ -4,7 +4,5 @@ enum class LitecoinNode(val host: String, val port: Int, val proto: String) { N_001("backup.electrum-ltc.org", 443, "ssl"), N_002("electrum-ltc.petrkr.net", 60002, "ssl"), N_003("electrum-ltc.bysh.me", 50002, "ssl"), - N_004("e-1.claudioboxx.com", 50004, "ssl"), - N_005("e-2.claudioboxx.com", 50004, "ssl"), - N_006("electrum.ltc.xurious.com", 50002, "ssl"), + N_004("electrum.ltc.xurious.com", 50002, "ssl"), } \ No newline at end of file From ab2804213ea1c1a3641654c12896f406eed98b68 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Apr 2019 15:52:20 +0300 Subject: [PATCH 20/28] Updated on 2026-08-14 --- .gitignore | 1 - app/libs/ripple-core-0.0.1.jar | Bin 0 -> 294113 bytes 2 files changed, 1 deletion(-) create mode 100644 app/libs/ripple-core-0.0.1.jar diff --git a/.gitignore b/.gitignore index 0a91f19203..ceb1b04599 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ /build /captures .externalNativeBuild -app/libs/ .idea/vcs.xml .idea/caches .idea/dictionaries diff --git a/app/libs/ripple-core-0.0.1.jar b/app/libs/ripple-core-0.0.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..617db52b2dc3b042561586280a4561da6abb6451 GIT binary patch literal 294113 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%0DUXU^8z-!B*<3ZTqWObRLC=0XKqT{~y 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 TDdUwm;a~-B=PDqz)oXQ=Om>e3a~@ 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%0D3SChhQW1|SY3%Io*5Vlh)yc^nq=I`#t-DdA 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 Jbuf?6{0{@{Ji7n@ literal 0 HcmV?d00001 From bed6098acbac38bdcac8967996445da233435117 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 4 Apr 2019 15:16:08 +0300 Subject: [PATCH 21/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BitcoinNode.kt | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt index d36b1b0789..c5f2a1d408 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt @@ -1,17 +1,11 @@ package com.tangem.domain.wallet.btc enum class BitcoinNode(val host: String, val port: Int, val proto: String) { - N_001("electrum.coinop.cc", 50002, "ssl"), - N_002("dedi.jochen-hoenicke.de", 50002, "ssl"), - N_003("technetium.network", 50002, "ssl"), - N_004("electrum.coinucopia.io", 50002, "ssl"), - N_005("dimon.trimon.de", 50002, "ssl"), - N_006("btc.gravitech.net", 50002, "ssl"), - N_007("fn.48.org", 50002, "ssl"), - N_008("vps.hsmiths.com", 50002, "ssl"), - N_009("electrum.qtornado.com", 50002, "ssl"), - N_010("electrum2.eff.ro", 50002, "ssl"), - N_011("electrum.hsmiths.com", 995, "ssl"), - N_012("electrum.hsmiths.com", 50002, "ssl"), - N_013("tardis.bauerj.eu", 50002, "ssl"), + N_001("dedi.jochen-hoenicke.de", 50002, "ssl"), + N_002("technetium.network", 50002, "ssl"), + N_003("btc.gravitech.net", 50002, "ssl"), + N_004("fn.48.org", 50002, "ssl"), + N_005("vps.hsmiths.com", 50002, "ssl"), + N_006("electrum.hsmiths.com", 995, "ssl"), + N_007("electrum.hsmiths.com", 50002, "ssl"), } \ No newline at end of file From e61bb892ae1684c66fa2314c791e8c87e6b84ef7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 4 Apr 2019 15:27:14 +0300 Subject: [PATCH 22/28] Updated on 2026-08-14 --- app/src/main/java/com/tangem/data/network/ServerApiElectrum.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java b/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java index a087030180..9b920fcace 100644 --- a/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java +++ b/app/src/main/java/com/tangem/data/network/ServerApiElectrum.java @@ -325,6 +325,7 @@ public class ServerApiElectrum { try { Log.i(TAG, host + " " + port); sslSocket = (SSLSocket) sf.createSocket(host, port); + sslSocket.setSoTimeout(3000); try { OutputStream os = sslSocket.getOutputStream(); OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8"); From aac43d8713ce5f3786595d2c033a44edd9d34ab0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 4 Apr 2019 18:37:08 +0300 Subject: [PATCH 23/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BitcoinNode.kt | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt index c5f2a1d408..b0fc29347a 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt @@ -1,11 +1,33 @@ package com.tangem.domain.wallet.btc enum class BitcoinNode(val host: String, val port: Int, val proto: String) { - N_001("dedi.jochen-hoenicke.de", 50002, "ssl"), - N_002("technetium.network", 50002, "ssl"), - N_003("btc.gravitech.net", 50002, "ssl"), - N_004("fn.48.org", 50002, "ssl"), - N_005("vps.hsmiths.com", 50002, "ssl"), - N_006("electrum.hsmiths.com", 995, "ssl"), - N_007("electrum.hsmiths.com", 50002, "ssl"), + N_001("dimon.trimon.de", 50001, "tcp"), + N_002("electrum.be", 50001, "tcp"), + N_003("electrum-lightning.cappux.com", 50001, "tcp"), + N_004("185.64.116.15", 50001, "tcp"), + N_005("electrum.noinput.xyz", 50001, "tcp"), + N_006("bitcoin.grey.pw", 50001, "tcp"), + N_007("139.162.14.142", 50001, "tcp"), + N_008("13.80.67.162", 50001, "tcp"), + N_009("207.154.223.80", 50001, "tcp"), + N_010("e.keff.org", 50001, "tcp"), + N_011("electrum.coinop.cc", 50002, "ssl"), + N_012("dedi.jochen-hoenicke.de", 50002, "ssl"), + N_013("technetium.network", 50002, "ssl"), + N_014("dimon.trimon.de", 50002, "ssl"), + N_015("btc.gravitech.net", 50002, "ssl"), + N_016("vps.hsmiths.com", 50002, "ssl"), + N_017("tomscryptos.com", 50002, "ssl"), + N_018("electrum.be", 50002, "ssl"), + N_019("95.216.28.117", 50002, "ssl"), + N_020("88.198.241.196", 50002, "ssl"), + N_021("electrum-lightning.cappux.com", 50002, "ssl"), + N_022("5.10.11.242", 50002, "ssl"), + N_023("84.195.61.95", 50002, "ssl"), + N_024("185.64.116.15", 50002, "ssl"), + N_025("electrum.mindspot.org", 50002, "ssl"), + N_026("172.103.153.90", 50002, "ssl"), + N_027("electrum.noinput.xyz", 50002, "ssl"), + N_028("bitcoin.grey.pw", 50002, "ssl"), + N_029("207.180.251.11", 50002, "ssl"), } \ No newline at end of file From 343a13325953c80985d1dd5aa3780eaddc61e235 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 5 Apr 2019 12:33:41 +0300 Subject: [PATCH 24/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BitcoinNode.kt | 56 +++++++++--------- app/src/main/res/raw/scan_card_sound.mp3 | Bin 20898 -> 2640 bytes 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt index b0fc29347a..7259769043 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BitcoinNode.kt @@ -1,33 +1,31 @@ package com.tangem.domain.wallet.btc enum class BitcoinNode(val host: String, val port: Int, val proto: String) { - N_001("dimon.trimon.de", 50001, "tcp"), - N_002("electrum.be", 50001, "tcp"), - N_003("electrum-lightning.cappux.com", 50001, "tcp"), - N_004("185.64.116.15", 50001, "tcp"), - N_005("electrum.noinput.xyz", 50001, "tcp"), - N_006("bitcoin.grey.pw", 50001, "tcp"), - N_007("139.162.14.142", 50001, "tcp"), - N_008("13.80.67.162", 50001, "tcp"), - N_009("207.154.223.80", 50001, "tcp"), - N_010("e.keff.org", 50001, "tcp"), - N_011("electrum.coinop.cc", 50002, "ssl"), - N_012("dedi.jochen-hoenicke.de", 50002, "ssl"), - N_013("technetium.network", 50002, "ssl"), - N_014("dimon.trimon.de", 50002, "ssl"), - N_015("btc.gravitech.net", 50002, "ssl"), - N_016("vps.hsmiths.com", 50002, "ssl"), - N_017("tomscryptos.com", 50002, "ssl"), - N_018("electrum.be", 50002, "ssl"), - N_019("95.216.28.117", 50002, "ssl"), - N_020("88.198.241.196", 50002, "ssl"), - N_021("electrum-lightning.cappux.com", 50002, "ssl"), - N_022("5.10.11.242", 50002, "ssl"), - N_023("84.195.61.95", 50002, "ssl"), - N_024("185.64.116.15", 50002, "ssl"), - N_025("electrum.mindspot.org", 50002, "ssl"), - N_026("172.103.153.90", 50002, "ssl"), - N_027("electrum.noinput.xyz", 50002, "ssl"), - N_028("bitcoin.grey.pw", 50002, "ssl"), - N_029("207.180.251.11", 50002, "ssl"), + N_001("electrum.be", 50001, "tcp"), + N_002("electrum-lightning.cappux.com", 50001, "tcp"), + N_003("185.64.116.15", 50001, "tcp"), + N_004("electrum.noinput.xyz", 50001, "tcp"), + N_005("bitcoin.grey.pw", 50001, "tcp"), + N_006("139.162.14.142", 50001, "tcp"), + N_007("13.80.67.162", 50001, "tcp"), + N_008("207.154.223.80", 50001, "tcp"), + N_009("e.keff.org", 50001, "tcp"), + N_010("electrum.coinop.cc", 50002, "ssl"), + N_011("dedi.jochen-hoenicke.de", 50002, "ssl"), + N_012("technetium.network", 50002, "ssl"), + N_013("btc.gravitech.net", 50002, "ssl"), + N_014("vps.hsmiths.com", 50002, "ssl"), + N_015("tomscryptos.com", 50002, "ssl"), + N_016("electrum.be", 50002, "ssl"), + N_017("95.216.28.117", 50002, "ssl"), + N_018("88.198.241.196", 50002, "ssl"), + N_019("electrum-lightning.cappux.com", 50002, "ssl"), + N_020("5.10.11.242", 50002, "ssl"), + N_021("84.195.61.95", 50002, "ssl"), + N_022("185.64.116.15", 50002, "ssl"), + N_023("electrum.mindspot.org", 50002, "ssl"), + N_024("172.103.153.90", 50002, "ssl"), + N_025("electrum.noinput.xyz", 50002, "ssl"), + N_026("bitcoin.grey.pw", 50002, "ssl"), + N_027("207.180.251.11", 50002, "ssl"), } \ No newline at end of file diff --git a/app/src/main/res/raw/scan_card_sound.mp3 b/app/src/main/res/raw/scan_card_sound.mp3 index 704f2441dff538e2a2aebef66ed70f8852337001..aa667e44635a4bd380baaa08d1ddc9a9df440107 100644 GIT binary patch literal 2640 zcmdT`c{tSF9zU}>5g~su40II~T~>^~8*nCEk=}#-!I0l7zI_ z3S(!~RhB0qNkWN4vi7^g3(zoJbgX0j8#-KA`AqHJe&7NC0^9kPr;>sU0bmyx zNIbY~@pgy~plyfvt;FExF$CSRNu8NB1)r(OwdHuo$7gmvKu<*4;eMmWT)VbSGGmse z?WnG=p0520qt#B)>bGq)4cerJ$^1ddFo&sBz4fnqLq3lTJ%OgIVV;L-5%}T4SsdVo z=1+th4NMDaVTJes(??%>`YM#hauO3jp+;pzqBAcw?iG#}#wl72`88#1WzQ9=LqCeQHWns43r zfvSeM$@vn;6%@vsyK^Rf$X&^?Yl`fV8u;A2dTW+;OdL{i)8Q7*xmWF&A*ii!;Wtm_ z_hsm=_gF+qZ+^Dxxkm=`01(I&UFSFVhlU}m%&{k71ztLvpREnaKjc>#<^dX{#;}mS>&f8Kn+FA)@@b=dl zNk^QtaiN|m0HIwQ_RrjaaIVDR`Z54Z$iE$<*AIY^I1X5^Dw!N=+nX=zdi?b{6U!H^ zWa0}PzE^S=B2bLe(tlJyTJ-EpYgdv|tVW5+pT;MQ=T3zO&^6E!DX|8c=T7g__m}8+ zJhbhuUPO7*yy3x&r!YTSyfo;$5};9bHMiKNm{0 ze<7ApQr53z88wdZ7j7f(($T=tgw}#P3Oi2{L$ZbJ@Z~G=gQ%9vJ=9aPMUE=YnavRC zu%uwpwo>y*==;&QGmzJVd5e?}S$Stg&MUSR@SMSJ4vfUF4x8aXM2Ch8Ics5o8Xfp? zrPjIMEcWa3XP_d*^rYo}r}pl9W|EkU$zHs&U)sM!ifG+ULF5OQT<5TTF4AI*Wj=4z zaN zZl!~;RnJm>LT-|(lubptj1#qLNx$vlgoSy+UV@2K#XA;-Nt;}8ke^;+lyfyA4O?&I zYzLV-sy-#ji%#|>$>E$6aa_~RdUd8jI$ULqjVQb#!g4CZ652Rj^iQJ`%MEeC6UFVR z2a%=}p!`*f{NS320S946($ij?fo3L{Z7~O1($X{A-dm(v8W*%MXb~`NZNKK7d$n8} z)3EsJX{OEP{JUCX0r2bXROdOTZva`4$hFrK1z0Q86RWo@T*8+zf6;k^qUbeUnx8Js zTle)I{g7i_RuW130d_qqt+l|oL`g$Nt6RXsv$oWs^pkaatA!e-uQjh#zD!UG52M4a zLScD96_jeB2R=6w1(2e4L^-c+YwZ^G&JG$rxov+GwR4Cd0E zM1d50B`JPqeWb1Rq<@-jcaM{@GNu-VZ1L-B9TVAjfVSmawi*9N-tlD!rq0!z#IaDhPvf@YK7)K86)0C<~`mml282s&y?49JW;U$G!rLp1B(BNZADOMI9%3(f4kiD-of3AW{c-N9xr-0BMoyGX zxaZ~jZPfivqX$Vg+xFf_=U;VK(?aAGE-*`WFtfu5X zb9!Qnr=0qoJNIXH0=buej+bv`oZ-|uv1Eu=nr>arjj<)wyGE-$zSfhhT2|`crGn}t zmj6!xfQRW(TL=%1O5sEISl-ikI?@pJ8g3e;R=)?@^s^R0=-kk>A5c9^b4JZI_;ts? zx-qt#M031d;w|zjR#>ZWIe8y8zX>+Lt6LP^YR0qwOwtTWZVv&Ufla zovQpTXQO}~NwfY{%@FScEH>5j(Pc(R7KQC3=NTon+dCg(v#7A@4F}tVnjQ=zmkp|g zEX;4#xVw9Tak@hqT|`vU{+OaqL}~H658gk2Od2|WCp@$%86<}J0zfb?aH0Va#_@tR UFBS8eys93Z7f%0f?tjz&Z>~R;!~g&Q literal 20898 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 From 036a8a5fbf8e5b53ba8059407c3903e8de9f8c0a Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 5 Apr 2019 12:44:56 +0300 Subject: [PATCH 25/28] Updated on 2026-08-14 --- app/src/main/java/com/tangem/data/Blockchain.java | 2 +- app/src/main/res/values/dimens.xml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/data/Blockchain.java b/app/src/main/java/com/tangem/data/Blockchain.java index 31e89d72ee..c613c3e3d6 100644 --- a/app/src/main/java/com/tangem/data/Blockchain.java +++ b/app/src/main/java/com/tangem/data/Blockchain.java @@ -16,7 +16,7 @@ public enum Blockchain { BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.ic_logo_bitcoin_cash, "Bitcoin Cash"), Litecoin("LTC", "LTC", 100000000.0, R.drawable.tangem2, "Litecoin"), Rootstock("RSK", "RBTC", 1.0, R.drawable.tangem2, "Rootstock"), - RootstockToken("Token", "RBTC", 1.0, R.drawable.tangem2, "Rootstock"), + RootstockToken("RskToken", "RBTC", 1.0, R.drawable.tangem2, "Rootstock"), Cardano("CARDANO", "ADA", 1000000.0, R.drawable.tangem2, "Cardano"), Ripple ("XRP", "XRP", 1000000.0, R.drawable.tangem2, "Ripple"); diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 8464ee95a5..1612a3d2a4 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -17,13 +17,13 @@ 140dp 16dp - 11sp - 13sp - 15sp - 19sp - 23sp - 26sp - 34sp + 11dp + 13dp + 15dp + 19dp + 23dp + 26dp + 34dp 180dp 30dp From faadb37ffb5cc04bea700a0e192e2dbc8ecf9a9d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 5 Apr 2019 14:07:30 +0300 Subject: [PATCH 26/28] Updated on 2026-08-14 --- app/src/main/res/layout/activity_confirm_transaction.xml | 2 +- app/src/main/res/layout/activity_main.xml | 2 +- app/src/main/res/layout/activity_pin_request.xml | 2 +- app/src/main/res/layout/activity_pin_save.xml | 2 +- app/src/main/res/layout/fr_loaded_wallet.xml | 2 +- app/src/main/res/layout/layout_tangem_card.xml | 2 +- app/src/main/res/layout/layout_touch_card.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/activity_confirm_transaction.xml b/app/src/main/res/layout/activity_confirm_transaction.xml index 6e10638831..5a48672aa3 100644 --- a/app/src/main/res/layout/activity_confirm_transaction.xml +++ b/app/src/main/res/layout/activity_confirm_transaction.xml @@ -139,7 +139,7 @@ android:layout_marginBottom="1dp" android:fontFamily="@font/maax" android:textColor="@color/primary" - android:textSize="14sp" + android:textSize="14dp" app:layout_constraintBottom_toBottomOf="@+id/textView3" app:layout_constraintLeft_toRightOf="@+id/textView3" tools:text="(including fee)" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index cc0bdcca10..48a209311f 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -30,7 +30,7 @@ android:layout_marginTop="12dp" android:fontFamily="@font/maax" android:gravity="center" - android:lineSpacingExtra="8sp" + android:lineSpacingExtra="8dp" android:minHeight="200dp" android:paddingLeft="20dp" android:paddingTop="20dp" diff --git a/app/src/main/res/layout/activity_pin_request.xml b/app/src/main/res/layout/activity_pin_request.xml index 3bdeda2f16..d0a3f210a5 100644 --- a/app/src/main/res/layout/activity_pin_request.xml +++ b/app/src/main/res/layout/activity_pin_request.xml @@ -15,7 +15,7 @@ android:paddingBottom="16dp" android:singleLine="false" android:textAlignment="center" - android:textSize="36sp" + android:textSize="36dp" tools:ignore="TextViewEdits" tools:text="1234" /> diff --git a/app/src/main/res/layout/activity_pin_save.xml b/app/src/main/res/layout/activity_pin_save.xml index 7475cab91a..c9c3d906bc 100644 --- a/app/src/main/res/layout/activity_pin_save.xml +++ b/app/src/main/res/layout/activity_pin_save.xml @@ -15,7 +15,7 @@ android:paddingBottom="8dp" android:singleLine="false" android:textAlignment="center" - android:textSize="36sp" + android:textSize="36dp" tools:ignore="TextViewEdits" /> diff --git a/app/src/main/res/layout/layout_tangem_card.xml b/app/src/main/res/layout/layout_tangem_card.xml index e7bc7d65d1..9b4136a6df 100644 --- a/app/src/main/res/layout/layout_tangem_card.xml +++ b/app/src/main/res/layout/layout_tangem_card.xml @@ -42,7 +42,7 @@ android:fontFamily="@font/maaxmedium" android:text="@string/verifying" android:textColor="@color/colorPrimary" - android:textSize="12sp" + android:textSize="12dp" android:textStyle="bold" /> Date: Fri, 5 Apr 2019 16:36:43 +0300 Subject: [PATCH 27/28] Updated on 2026-08-14 --- .../tangem/domain/wallet/btc/BtcEngine.java | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java b/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java index 824bee559a..3e248c2bef 100644 --- a/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/btc/BtcEngine.java @@ -768,30 +768,26 @@ public class BtcEngine extends CoinEngine { final ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() { @Override public void onSuccess(ElectrumRequest electrumRequest) { - BigDecimal fee; + BigDecimal kbFee; if (electrumRequest.isMethod(ElectrumRequest.METHOD_GetFee)) { try { - fee = new BigDecimal(electrumRequest.getResultString()); //fee per KB + kbFee = new BigDecimal(electrumRequest.getResultString()); //fee per KB - if (fee.equals(BigDecimal.ZERO)) { + if (kbFee.equals(BigDecimal.ZERO)) { serverApiElectrum.requestData(ctx, ElectrumRequest.getFee()); } -// if (calcSize != 0) { - fee = fee.multiply(new BigDecimal(calcSize)).divide(new BigDecimal(1024)); // (per KB -> per byte)*size -// } else { -// serverApiElectrum.requestData(ctx, ElectrumRequest.getFee()); -// } + BigDecimal minByteFee = kbFee.divide(new BigDecimal(1024)); // per KB -> per byte + BigDecimal normalByteFee = minByteFee.add(new BigDecimal(0.00000010)); + BigDecimal maxByteFee = minByteFee.add(new BigDecimal(0.00000025)); - //compare fee to usual relay fee -// if (fee.compareTo(relayFee) < 0) { -// fee = relayFee; -// } - fee = fee.setScale(8, RoundingMode.DOWN); + BigDecimal minFee = minByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN); + BigDecimal normalFee = normalByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN); + BigDecimal maxFee = maxByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN); - CoinEngine.Amount minAmount = new CoinEngine.Amount(fee, ctx.getBlockchain().getCurrency()); - CoinEngine.Amount normalAmount = new CoinEngine.Amount(fee.multiply(new BigDecimal(3)), ctx.getBlockchain().getCurrency()); - CoinEngine.Amount maxAmount = new CoinEngine.Amount(fee.multiply(new BigDecimal(6)), ctx.getBlockchain().getCurrency()); + CoinEngine.Amount minAmount = new CoinEngine.Amount(minFee, ctx.getBlockchain().getCurrency()); + CoinEngine.Amount normalAmount = new CoinEngine.Amount(normalFee, ctx.getBlockchain().getCurrency()); + CoinEngine.Amount maxAmount = new CoinEngine.Amount(maxFee, ctx.getBlockchain().getCurrency()); coinData.minFee = minAmount; coinData.normalFee = normalAmount; From 86e09de943644cbd89f402533e393acaa5daecd7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 5 Apr 2019 16:42:54 +0300 Subject: [PATCH 28/28] Updated on 2026-08-14 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b654558186..f368ea6864 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "com.tangem.wallet" minSdkVersion 21 targetSdkVersion 28 - versionCode 106 - versionName "0.903.2." + generateVersionName() + versionCode 107 + versionName "0.904.1." + generateVersionName() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } androidExtensions {