From 6cd722e735ad150cb5a09ca3b616a6259b1ee9a6 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:17:34 +0100 Subject: [PATCH 1/8] Update testchain.json --- testnet/testchain.json | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/testnet/testchain.json b/testnet/testchain.json index 089bd693..66287bef 100644 --- a/testnet/testchain.json +++ b/testnet/testchain.json @@ -27,6 +27,9 @@ "onlineAccountsModulusV2Timestamp": 0, "selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999, "mempowTransactionUpdatesTimestamp": 1692554400000, + "blockRewardBatchStartHeight": 10000, + "blockRewardBatchSize": 1000, + "blockRewardBatchAccountsBlockCount": 25, "rewardsByHeight": [ { "height": 1, "reward": 5.00 }, { "height": 259201, "reward": 4.75 }, @@ -69,8 +72,8 @@ ], "ciyamAtSettings": { "feePerStep": "0.00000001", - "maxStepsPerRound": 500, - "stepsPerFunctionCall": 10, + "maxStepsPerRound": 1000, + "stepsPerFunctionCall": 100, "minutesPerBlock": 1 }, "featureTriggers": { @@ -89,11 +92,11 @@ "selfSponsorshipAlgoV1Height": 9999999, "feeValidationFixTimestamp": 0, "chatReferenceTimestamp": 0, - "arbitraryOptionalFeeTimestamp": 1678622400000 + "arbitraryOptionalFeeTimestamp": 0 }, "genesisInfo": { "version": 4, - "timestamp": "1677572542000", + "timestamp": "1701874800000", "transactions": [ { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORTAL coin", "quantity": 0, "isDivisible": true, "data": "{}" }, { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, @@ -2661,4 +2664,4 @@ { "type": "GENESIS", "recipient": "QU7EUWDZz7qJVPih3wL9RKTHRfPFy4ASHC", "amount": 10 } ] } -} \ No newline at end of file +} From b266d205b140f264ba973505dff57cd9545b5a1f Mon Sep 17 00:00:00 2001 From: QuickMythril Date: Fri, 8 Dec 2023 18:11:02 -0500 Subject: [PATCH 2/8] Added Hebrew translations --- .../resources/i18n/ApiError_he.properties | 83 ++++++++ src/main/resources/i18n/SysTray_he.properties | 48 +++++ .../i18n/TransactionValidity_he.properties | 195 ++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 src/main/resources/i18n/ApiError_he.properties create mode 100644 src/main/resources/i18n/SysTray_he.properties create mode 100644 src/main/resources/i18n/TransactionValidity_he.properties diff --git a/src/main/resources/i18n/ApiError_he.properties b/src/main/resources/i18n/ApiError_he.properties new file mode 100644 index 00000000..5ce597f4 --- /dev/null +++ b/src/main/resources/i18n/ApiError_he.properties @@ -0,0 +1,83 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +# Keys are from api.ApiError enum + +# "localeLang": "he", + +### Common ### +JSON = נכשל בניתוח הודעת JSON + +INSUFFICIENT_BALANCE = יתרה לא מספקת + +UNAUTHORIZED = קריאת API לא מורשית + +REPOSITORY_ISSUE = שגיאת מאגר + +NON_PRODUCTION = קריאת API זו אינה מותרת עבור מערכות ייצור + +BLOCKCHAIN_NEEDS_SYNC = הבלוקצ'יין צריך להסתנכרן תחילה + +NO_TIME_SYNC = עדיין אין סנכרון שעון + +### Validation ### +INVALID_SIGNATURE = חתימה לא חוקית + +INVALID_ADDRESS = כתובת לא חוקית + +INVALID_PUBLIC_KEY = מפתח ציבורי לא חוקי + +INVALID_DATA = נתונים לא חוקיים + +INVALID_NETWORK_ADDRESS = כתובת רשת לא חוקית + +ADDRESS_UNKNOWN = כתובת חשבון לא ידועה + +INVALID_CRITERIA = קריטריוני חיפוש לא חוקיים + +INVALID_REFERENCE = הפניה לא חוקית + +TRANSFORMATION_ERROR = לא הצליח להפוך את JSON לעסקה + +INVALID_PRIVATE_KEY = מפתח פרטי לא חוקי + +INVALID_HEIGHT = גובה בלוק לא חוקי + +CANNOT_MINT = החשבון לא יכול להטביע + +### Blocks ### +BLOCK_UNKNOWN = בלוק לא ידוע + +### Transactions ### +TRANSACTION_UNKNOWN = עסקה לא ידועה + +PUBLIC_KEY_NOT_FOUND = מפתח ציבורי לא נמצא + +# this one is special in that caller expected to pass two additional strings, hence the two %s +TRANSACTION_INVALID = עסקה לא חוקית: %s (%s) + +### Naming ### +NAME_UNKNOWN = שם לא ידוע + +### Asset ### +INVALID_ASSET_ID = מזהה נכס לא חוקי + +INVALID_ORDER_ID = מזהה הזמנת נכס לא חוקי + +ORDER_UNKNOWN = מזהה הזמנת נכס לא ידוע + +### Groups ### +GROUP_UNKNOWN = קבוצה לא ידועה + +### Foreign Blockchain ### +FOREIGN_BLOCKCHAIN_NETWORK_ISSUE = בעיה זרה בלוקצ'יין או ElectrumX ברשת + +FOREIGN_BLOCKCHAIN_BALANCE_ISSUE = יתרה לא מספקת בבלוקצ'יין זר + +FOREIGN_BLOCKCHAIN_TOO_SOON = מוקדם מדי לשדר עסקת בלוקצ'יין זרה (זמן נעילה/זמן חסימה חציוני) + +### Trade Portal ### +ORDER_SIZE_TOO_SMALL = כמות ההזמנה נמוכה מדי + +### Data ### +FILE_NOT_FOUND = הקובץ לא נמצא + +NO_REPLY = עמית לא השיב בזמן המותר diff --git a/src/main/resources/i18n/SysTray_he.properties b/src/main/resources/i18n/SysTray_he.properties new file mode 100644 index 00000000..50ef8933 --- /dev/null +++ b/src/main/resources/i18n/SysTray_he.properties @@ -0,0 +1,48 @@ +#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/) +# SysTray pop-up menu + +APPLYING_UPDATE_AND_RESTARTING = מחיל עדכון אוטומטי ומפעיל מחדש... + +AUTO_UPDATE = עדכון אוטומטי + +BLOCK_HEIGHT = גובה + +BLOCKS_REMAINING = נותרו בלוקים + +BUILD_VERSION = גרסת בנייה + +CHECK_TIME_ACCURACY = בדוק את דיוק הזמן + +CONNECTING = מתחבר + +CONNECTION = חיבור + +CONNECTIONS = חיבורים + +CREATING_BACKUP_OF_DB_FILES = יוצר גיבוי של קבצי מסד נתונים... + +DB_BACKUP = גיבוי מסד נתונים + +DB_CHECKPOINT = נקודת ביקורת של מסד נתונים + +DB_MAINTENANCE = תחזוקת מסד נתונים + +EXIT = יציאה + +LITE_NODE = Lite Node + +MINTING_DISABLED = כרייה מבוטלת + +MINTING_ENABLED = \u2714 הטבעה + +OPEN_UI = ממשק משתמש פתוח + +PERFORMING_DB_CHECKPOINT = שומר שינויים לא מחויבים במסד הנתונים... + +PERFORMING_DB_MAINTENANCE = מבצע תחזוקה מתוזמנת... + +SYNCHRONIZE_CLOCK = סנכרן שעון + +SYNCHRONIZING_BLOCKCHAIN ​​= מסנכרן + +SYNCHRONIZING_CLOCK = מסנכרן שעון diff --git a/src/main/resources/i18n/TransactionValidity_he.properties b/src/main/resources/i18n/TransactionValidity_he.properties new file mode 100644 index 00000000..889d7b78 --- /dev/null +++ b/src/main/resources/i18n/TransactionValidity_he.properties @@ -0,0 +1,195 @@ +# + +ACCOUNT_ALREADY_EXISTS = חשבון כבר קיים + +ACCOUNT_CANNOT_REWARD_SHARE = ​​חשבון לא יכול לחלוק תגמולים + +ADDRESS_ABOVE_RATE_LIMIT = הכתובת הגיעה למגבלת התעריף שצוינה + +ADDRESS_BLOCKED = כתובת זו חסומה + +ALREADY_GROUP_ADMIN = כבר מנהל קבוצה + +ALREADY_GROUP_MEMBER = כבר חבר בקבוצה + +ALREADY_VOTED_FOR_THAT_OPTION = כבר הצביע עבור אפשרות זו + +ASSET_ALREADY_EXISTS = הנכס כבר קיים + +ASSET_DOES_NOT_EXIST = הנכס אינו קיים + +ASSET_DOES_NOT_MATCH_AT = הנכס אינו תואם לנכס של AT + +ASSET_NOT_SPENDABLE = הנכס אינו ניתן לבזבז + +AT_ALREADY_EXISTS = AT כבר קיים + +AT_IS_FINISHED = AT הסתיים + +AT_UNKNOWN = AT לא ידוע + +BAN_EXISTS = החסימה כבר קיימת + +BAN_UNKNOWN = איסור לא ידוע + +BANNED_FROM_GROUP = חסום מהקבוצה + +BUYER_ALREADY_OWNER = הקונה כבר הבעלים + +CLOCK_NOT_SYNCED = שעון לא מסונכרן + +DUPLICATE_MESSAGE = כתובת שנשלחה הודעה כפולה + +DUPLICATE_OPTION = אפשרות שכפול + +GROUP_ALREADY_EXISTS = הקבוצה כבר קיימת + +GROUP_APPROVAL_DECIDED = אישור הקבוצה כבר הוחלט + +GROUP_APPROVAL_NOT_REQUIRED = אין צורך באישור קבוצתי + +GROUP_DOES_NOT_EXIST = קבוצה לא קיימת + +GROUP_ID_MISMATCH = אי התאמה של מזהה הקבוצה + +GROUP_OWNER_CANNOT_LEAVE = בעל הקבוצה לא יכול לעזוב את הקבוצה + +HAVE_EQUALS_WANT = have-asset זהה ל-want-asset + +INCORRECT_NONCE = לא תקין של PoW + +INSUFFICIENT_FEE = עמלה לא מספקת + +INVALID_ADDRESS = כתובת לא חוקית + +INVALID_AMOUNT = סכום לא חוקי + +INVALID_ASSET_OWNER = בעל נכס לא חוקי + +INVALID_AT_TRANSACTION = עסקת AT לא חוקית + +INVALID_AT_TYPE_LENGTH = אורך AT 'סוג' לא חוקי + +INVALID_BUT_OK = לא חוקי אבל בסדר + +INVALID_CREATION_BYTES = בתים לא חוקיים של יצירה + +INVALID_DATA_LENGTH = אורך נתונים לא חוקי + +INVALID_DESCRIPTION_LENGTH = אורך תיאור לא חוקי + +INVALID_GROUP_APPROVAL_THRESHOLD = סף לא חוקי לאישור קבוצה + +INVALID_GROUP_BLOCK_DELAY = עיכוב חסימת אישור קבוצה לא חוקי + +INVALID_GROUP_ID = מזהה קבוצה לא חוקי + +INVALID_GROUP_OWNER = בעל קבוצה לא חוקי + +INVALID_LIFETIME = משך חיים לא חוקי + +INVALID_NAME_LENGTH = אורך שם לא חוקי + +INVALID_NAME_OWNER = בעל שם לא חוקי + +INVALID_OPTION_LENGTH = אורך אפשרויות לא חוקי + +INVALID_OPTIONS_COUNT = ספירת אפשרויות לא חוקיות + +INVALID_ORDER_CREATOR = יוצר הזמנה לא חוקי + +INVALID_PAYMENTS_COUNT = ספירת תשלומים לא חוקיים + +INVALID_PUBLIC_KEY = מפתח ציבורי לא חוקי + +INVALID_QUANTITY = כמות לא חוקית + +INVALID_REFERENCE = הפניה לא חוקית + +INVALID_RETURN = החזרה לא חוקית + +INVALID_REWARD_SHARE_PERCENT = אחוז חלוקת תגמולים לא חוקי + +INVALID_SELLER = מוכר לא חוקי + +INVALID_TAGS_LENGTH = אורך 'תגים' לא חוקי + +INVALID_TIMESTAMP_SIGNATURE = חתימת חותמת זמן לא חוקית + +INVALID_TX_GROUP_ID = מזהה קבוצת עסקאות לא חוקי + +INVALID_VALUE_LENGTH = אורך 'ערך' לא חוקי + +INVITE_UNKNOWN = הזמנה לקבוצה לא ידועה + +JOIN_REQUEST_EXISTS = בקשת הצטרפות לקבוצה כבר קיימת + +MAXIMUM_REWARD_SHARES = כבר במספר המרבי של שיתופי תגמול עבור חשבון זה + +MISSING_CREATOR = חסר יוצר + +MULTIPLE_NAMES_FORBIDDEN = אסור להשתמש במספר שמות רשומים לכל חשבון + +NAME_ALREADY_FOR_SALE = שם כבר למכירה + +NAME_ALREADY_REGISTERED = השם כבר רשום + +NAME_BLOCKED = השם הזה חסום + +NAME_DOES_NOT_EXIST = שם לא קיים + +NAME_NOT_FOR_SALE = השם אינו למכירה + +NAME_NOT_NORMALIZED = שם לא בצורת Unicode 'מנורמלת' + +NEGATIVE_AMOUNT = סכום לא חוקי/שלילי + +NEGATIVE_FEE = עמלה לא חוקית/שלילית + +NEGATIVE_PRICE = מחיר לא חוקי/שלילי + +NO_BALANCE = איזון לא מספיק + +NO_BLOCKCHAIN_LOCK = הבלוקצ'יין של הצומת תפוס כעת + +NO_FLAG_PERMISSION = לחשבון אין הרשאה זו + +NOT_GROUP_ADMIN = החשבון אינו מנהל קבוצה + +NOT_GROUP_MEMBER = החשבון אינו חבר בקבוצה + +NOT_MINTING_ACCOUNT = החשבון אינו יכול להטביע + +NOT_YET_RELEASED = תכונה עדיין לא שוחררה + +OK = בסדר + +ORDER_ALREADY_CLOSED = הזמנת סחר בנכס כבר סגורה + +ORDER_DOES_NOT_EXIST = הוראת סחר בנכס לא קיימת + +POLL_ALREADY_EXISTS = סקר כבר קיים + +POLL_DOES_NOT_EXIST = סקר אינו קיים + +POLL_OPTION_DOES_NOT_EXIST = אפשרות סקר לא קיימת + +PUBLIC_KEY_UNKNOWN = מפתח ציבורי לא ידוע + +REWARD_SHARE_UNKNOWN = חלוקת פרס לא ידוע + +SELF_SHARE_EXISTS = שיתוף עצמי (שיתוף תגמול) כבר קיים + +TIMESTAMP_TOO_NEW = חותמת זמן חדשה מדי + +TIMESTAMP_TOO_OLD = חותמת זמן ישנה מדי + +TOO_MANY_UNCONFIRMED = בחשבון יש יותר מדי עסקאות לא מאושרות בהמתנה + +TRANSACTION_ALREADY_CONFIRMED = העסקה כבר אושרה + +TRANSACTION_ALREADY_EXISTS = עסקה כבר קיימת + +TRANSACTION_UNKNOWN = עסקה לא ידועה + +TX_GROUP_ID_MISMATCH = מזהה הקבוצה של העסקה אינו תואם From 5054773761f0b4312a0a90360324d66688965582 Mon Sep 17 00:00:00 2001 From: catbref Date: Sun, 10 Dec 2023 14:03:47 +0000 Subject: [PATCH 3/8] Chain AT-transaction references to avoid duplicates --- src/main/java/org/qortal/at/QortalATAPI.java | 4 + .../org/qortal/test/at/CrowdfundTests.java | 425 ++++++++++++++++++ 2 files changed, 429 insertions(+) create mode 100644 src/test/java/org/qortal/test/at/CrowdfundTests.java diff --git a/src/main/java/org/qortal/at/QortalATAPI.java b/src/main/java/org/qortal/at/QortalATAPI.java index 93dac568..276116fc 100644 --- a/src/main/java/org/qortal/at/QortalATAPI.java +++ b/src/main/java/org/qortal/at/QortalATAPI.java @@ -522,6 +522,10 @@ public class QortalATAPI extends API { /** Returns AT account's lastReference */ private byte[] getLastReference() { + // If we have transactions already, then use signature from last transaction + if (!this.transactions.isEmpty()) + return this.transactions.get(this.transactions.size() - 1).getTransactionData().getSignature(); + try { // Look up AT's account's last reference from repository Account atAccount = this.getATAccount(); diff --git a/src/test/java/org/qortal/test/at/CrowdfundTests.java b/src/test/java/org/qortal/test/at/CrowdfundTests.java new file mode 100644 index 00000000..6a60c1ab --- /dev/null +++ b/src/test/java/org/qortal/test/at/CrowdfundTests.java @@ -0,0 +1,425 @@ +package org.qortal.test.at; + +import org.ciyam.at.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.qortal.account.Account; +import org.qortal.account.PrivateKeyAccount; +import org.qortal.asset.Asset; +import org.qortal.at.AT; +import org.qortal.block.Block; +import org.qortal.data.at.ATData; +import org.qortal.data.at.ATStateData; +import org.qortal.data.block.BlockData; +import org.qortal.data.transaction.*; +import org.qortal.group.Group; +import org.qortal.repository.DataException; +import org.qortal.repository.Repository; +import org.qortal.repository.RepositoryManager; +import org.qortal.test.common.*; +import org.qortal.transaction.*; +import org.qortal.utils.*; + +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.junit.Assert.*; + +public class CrowdfundTests extends Common { + + /* + "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" + "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" + "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000" + "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000" + */ + + private static final String aliceAddress = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v"; + private static final String bobAddress = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK"; + private static final String chloeAddress = "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL"; + private static final String dilbertAddress = "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er"; + + // Creation bytes from: java -cp 'target/qrowdfund-1.0.0.jar:target/dependency/*' org.qortal.at.qrowdfund.Qrowdfund 50 12385 Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er + private static final String creationBytes58 = "1Pub6o13xyqfCZj8BMzmXsREVJR6h4xxpS2VPV1R2QwjP78r2ozxsNuvb28GWrT8FoTTQMGnVP7pNii6auUqYr2uunWfcxwhERbDgFdsJqtrJMpQNGB9GerAXYyiFiij35cP6eHw7BmALb3viT6VzqaXX9YB25iztekV5cTreJg7o2hRpFc9Rv8Z9dFXcD1Mm4WCaMaknUgchDi7qDnHA7JX8bn9EFD4WMG5nZHMsrmeqBHirURXr2dMxFprTBo187zztmw7izbv5KzMFP8aRP9uEqdTMhZJmvKqhapMK9UJkxMve3KnsxKn5yyaAeiZ4i9GNfrkjpz5T1VGomUaDmeatNti1bjQ2pwtcgZfFFbrnBFMU2kvcPx1UR53dArtRS7pFbNr3EFwnw2Yiu2xS3Z"; + private static final byte[] creationBytes = Base58.decode(creationBytes58); + private static final long fundingAmount = 2_00000000L; + private static final long SLEEP_PERIOD = 50L; + + private Repository repository = null; + private PrivateKeyAccount deployer; + private DeployAtTransaction deployAtTransaction; + private Account atAccount; + private String atAddress; + private byte[] rawLastTxnTimestamp = new byte[8]; + private Transaction transaction; + + @Before + public void before() throws DataException { + Common.useDefaultSettings(); + + this.repository = RepositoryManager.getRepository(); + this.deployer = Common.getTestAccount(repository, "alice"); + + this.deployAtTransaction = doDeploy(repository, deployer, creationBytes, fundingAmount); + this.atAccount = deployAtTransaction.getATAccount(); + this.atAddress = deployAtTransaction.getATAccount().getAddress(); + } + + @After + public void after() throws DataException { + if (this.repository != null) + this.repository.close(); + + this.repository = null; + } + + @Test + public void testDeploy() throws DataException { + // Confirm initial value is zero + extractLastTxTimestamp(repository, atAddress, rawLastTxnTimestamp); + assertArrayEquals(new byte[8], rawLastTxnTimestamp); + } + + @Test + public void testThresholdNotMet() throws DataException { + // AT deployment in block 2 + + // Mint block to allow AT to initialize and call SLEEP_UNTIL_MESSAGE_OR_HEIGHT + BlockUtils.mintBlock(repository); // height now 3 + + // Fetch AT's balance for this height + long preMintBalance = atAccount.getConfirmedBalance(Asset.QORT); + + // Fetch AT's initial lastTxnTimestamp + byte[] creationTimestamp = new byte[8]; + extractLastTxTimestamp(repository, atAddress, creationTimestamp); + + // Mint several blocks + int i = repository.getBlockRepository().getBlockchainHeight(); + long WAKE_HEIGHT = i + SLEEP_PERIOD; + for (; i < WAKE_HEIGHT; ++i) + BlockUtils.mintBlock(repository); + + // We should now be at WAKE_HEIGHT + long height = repository.getBlockRepository().getBlockchainHeight(); + assertEquals(WAKE_HEIGHT, height); + + // AT should have woken and run at this height so balance should have changed + + // Fetch new AT balance + long postMintBalance = atAccount.getConfirmedBalance(Asset.QORT); + + assertNotSame(preMintBalance, postMintBalance); + + // Confirm AT has found no payments + extractLastTxTimestamp(repository, atAddress, rawLastTxnTimestamp); + assertArrayEquals(creationTimestamp, rawLastTxnTimestamp); + + // AT should have finished + ATData atData = repository.getATRepository().fromATAddress(atAddress); + assertTrue(atData.getIsFinished()); + + // AT should have sent balance back to creator + BlockData blockData = repository.getBlockRepository().getLastBlock(); + Block block = new Block(repository, blockData); + List transactions = block.getTransactions(); + + assertEquals(1, transactions.size()); + + Transaction transaction = transactions.get(0); + AtTransaction atTransaction = (AtTransaction) transaction; + assertEquals(aliceAddress, atTransaction.getRecipient().getAddress()); + } + + @Test + public void testThresholdNotMetWithOrphanage() throws DataException { + // AT deployment in block 2 + + // Mint block to allow AT to initialize and call SLEEP_UNTIL_MESSAGE_OR_HEIGHT + BlockUtils.mintBlock(repository); // height now 3 + + // Fetch AT's initial lastTxnTimestamp + byte[] creationTimestamp = new byte[8]; + extractLastTxTimestamp(repository, atAddress, creationTimestamp); + + // Mint several blocks + int i = repository.getBlockRepository().getBlockchainHeight(); + long WAKE_HEIGHT = i + SLEEP_PERIOD; + for (; i < WAKE_HEIGHT; ++i) + BlockUtils.mintBlock(repository); + + // AT should have finished + ATData atData = repository.getATRepository().fromATAddress(atAddress); + assertTrue(atData.getIsFinished()); + + // Orphan + BlockUtils.orphanBlocks(repository, 3); + + // Mint several blocks + for (i = 0; i < 3; ++i) + BlockUtils.mintBlock(repository); + + // Confirm AT has found no payments + extractLastTxTimestamp(repository, atAddress, rawLastTxnTimestamp); + assertArrayEquals(creationTimestamp, rawLastTxnTimestamp); + + // AT should have finished + atData = repository.getATRepository().fromATAddress(atAddress); + assertTrue(atData.getIsFinished()); + + // AT should have sent balance back to creator + BlockData blockData = repository.getBlockRepository().getLastBlock(); + Block block = new Block(repository, blockData); + List transactions = block.getTransactions(); + + assertEquals(1, transactions.size()); + + Transaction transaction = transactions.get(0); + AtTransaction atTransaction = (AtTransaction) transaction; + assertEquals(aliceAddress, atTransaction.getRecipient().getAddress()); + } + + @Test + public void testThresholdNotMetWithPaymentsAndRefunds() throws DataException { + // AT deployment in block 2 + + // Mint block to allow AT to initialize and call SLEEP_UNTIL_MESSAGE_OR_HEIGHT + BlockUtils.mintBlock(repository); // height now 3 + + // Fetch AT's balance for this height + long preMintBalance = atAccount.getConfirmedBalance(Asset.QORT); + + // Fetch AT's initial lastTxnTimestamp + byte[] creationTimestamp = new byte[8]; + extractLastTxTimestamp(repository, atAddress, creationTimestamp); + + int i = repository.getBlockRepository().getBlockchainHeight(); + long WAKE_HEIGHT = i + SLEEP_PERIOD; + + // Create some test accounts, based on donations + List> donations = List.of( + new Pair<>("QRt11DVBnLaSDxr2KHvx92LdPrjhbhJtkj", 500L), + new Pair<>("QRv7tHnaEpRtfovbTJqkJFmtnoahJrbPGg", 250L), + new Pair<>("QRv7tHnaEpRtfovbTJqkJFmtnoahJrbPGg", 250L), + new Pair<>("QczG8GXU5vPQLTZsJBASQd3fAKJzKwnubv", 250L), + new Pair<>("QNuYHyW4HJn7v3dYUxoTLiyS5tpGQAguMJ", 20L), + new Pair<>("QgVqcSZZ6HRhBvdUmpTvEonaQaH2oWfe58", 500L), + new Pair<>("QfDaxmD8jKi3TovWA1NA8RL5rWYXRC12uX", 10L), + new Pair<>("QSohMWUphRwtEuwAZKqoy8UGS13tk1bBDm", 15L), + new Pair<>("QiNKXRfnX9mTodSed1yRQexhL1HA42RHHo", 420L), + new Pair<>("Qgfh143pRJyxpS92JoazjXNMH1uZueQBZ2", 100L), + new Pair<>("Qgfh143pRJyxpS92JoazjXNMH1uZueQBZ2", 100L) + ); + Map donors = donations.stream() + .map(donation -> donation.getA()) + .distinct() + .collect(Collectors.toMap(name -> name, name -> generateTestAccount(repository, name))); + + // Give donors some QORT so they can donate + donors.values() + .stream() + .forEach(donorAccount -> { + try { + AccountUtils.pay(repository, Common.getTestAccount(repository, "alice"), donorAccount.getAddress(), 2000_00000000L); + } catch (DataException e) { + fail(e.getMessage()); + } + }); + + // Record balances + Map initialDonorBalances = donors.values() + .stream() + .collect(Collectors.toMap(account -> account.getAddress(), account -> { + try { + return account.getConfirmedBalance(Asset.QORT); + } catch (DataException e) { + fail(e.getMessage()); + return null; + } + })); + + // Now make donations + donations.stream() + .forEach(donation -> { + TestAccount donorAccount = donors.get(donation.getA()); + try { + AccountUtils.pay(repository, donorAccount, atAddress, donation.getB() * 1_00000000L); + System.out.printf("AT balance at height %d is %s\n", repository.getBlockRepository().getBlockchainHeight(), Amounts.prettyAmount(atAccount.getConfirmedBalance(Asset.QORT))); + } catch (DataException e) { + fail(e.getMessage()); + } + }); + + // Mint several blocks + i = repository.getBlockRepository().getBlockchainHeight(); + for (; i < WAKE_HEIGHT; ++i) { + BlockUtils.mintBlock(repository); + System.out.printf("AT balance at height %d is %s\n", repository.getBlockRepository().getBlockchainHeight(), Amounts.prettyAmount(atAccount.getConfirmedBalance(Asset.QORT))); + } + + // We should now be at WAKE_HEIGHT + long height = repository.getBlockRepository().getBlockchainHeight(); + assertEquals(WAKE_HEIGHT, height); + + // AT should have woken and run at this height so balance should have changed + System.out.printf("AT balance at height %d is %s\n", repository.getBlockRepository().getBlockchainHeight(), Amounts.prettyAmount(atAccount.getConfirmedBalance(Asset.QORT))); + + // Fetch new AT balance + long postMintBalance = atAccount.getConfirmedBalance(Asset.QORT); + + assertNotSame(preMintBalance, postMintBalance); + + + // Payments might happen over multiple blocks! + Map expectedBalances = new HashMap<>(initialDonorBalances); + + ATData atData; + do { + // Confirm AT has found payments + extractLastTxTimestamp(repository, atAddress, rawLastTxnTimestamp); + assertNotSame(ByteArray.wrap(creationTimestamp), ByteArray.copyOf(rawLastTxnTimestamp)); + + // AT should have sent refunds + BlockData blockData = repository.getBlockRepository().getLastBlock(); + Block block = new Block(repository, blockData); + List transactions = block.getTransactions(); + + assertNotSame(0, transactions.size()); + + // Compute expected balances + for (var transaction : transactions) { + AtTransaction atTransaction = (AtTransaction) transaction; + ATTransactionData atTransactionData = (ATTransactionData) atTransaction.getTransactionData(); + String recipient = atTransactionData.getRecipient(); + + // Skip if this is a refund to AT deployer + if (recipient.equals(aliceAddress)) + continue; + + String donorName = donors.entrySet() + .stream() + .filter(donor -> donor.getValue().getAddress().equals(recipient)) + .findFirst() + .get() + .getKey(); + System.out.printf("AT paid %s to %s\n", Amounts.prettyAmount(atTransactionData.getAmount()), donorName); + + expectedBalances.compute(atTransactionData.getRecipient(), (key, balance) -> balance - AccountUtils.fee); + } + + // AT should have finished + atData = repository.getATRepository().fromATAddress(atAddress); + + // Mint new block in case we need to loop round again + BlockUtils.mintBlock(repository); + System.out.printf("AT balance at height %d is %s\n", repository.getBlockRepository().getBlockchainHeight(), Amounts.prettyAmount(atAccount.getConfirmedBalance(Asset.QORT))); + } while (!atData.getIsFinished()); + + // Compare expected balances + donors.entrySet() + .forEach(donor -> { + String donorName = donor.getKey(); + TestAccount donorAccount = donor.getValue(); + + Long expectedBalance = expectedBalances.get(donorAccount.getAddress()); + Long actualBalance = null; + try { + actualBalance = donorAccount.getConfirmedBalance(Asset.QORT); + } catch (DataException e) { + fail(e.getMessage()); + } + + assertEquals(expectedBalance, actualBalance); + }); + } + + + private DeployAtTransaction doDeploy(Repository repository, PrivateKeyAccount deployer, byte[] creationBytes, long fundingAmount) throws DataException { + long txTimestamp = System.currentTimeMillis(); + byte[] lastReference = deployer.getLastReference(); + + if (lastReference == null) { + System.err.println(String.format("Qortal account %s has no last reference", deployer.getAddress())); + System.exit(2); + } + + Long fee = null; + String name = "Test AT"; + String description = "Test AT"; + String atType = "Test"; + String tags = "TEST"; + + BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, deployer.getPublicKey(), fee, null); + TransactionData deployAtTransactionData = new DeployAtTransactionData(baseTransactionData, name, description, atType, tags, creationBytes, fundingAmount, Asset.QORT); + + DeployAtTransaction deployAtTransaction = new DeployAtTransaction(repository, deployAtTransactionData); + + fee = deployAtTransaction.calcRecommendedFee(); + deployAtTransactionData.setFee(fee); + + TransactionUtils.signAndMint(repository, deployAtTransactionData, deployer); + + return deployAtTransaction; + } + + private void extractLastTxTimestamp(Repository repository, String atAddress, byte[] rawLastTxnTimestamp) throws DataException { + // Check AT result + ATStateData atStateData = repository.getATRepository().getLatestATState(atAddress); + byte[] stateData = atStateData.getStateData(); + + byte[] dataBytes = MachineState.extractDataBytes(stateData); + + System.arraycopy(dataBytes, 5 * MachineState.VALUE_SIZE, rawLastTxnTimestamp, 0, rawLastTxnTimestamp.length); + } + + private void assertTimestamp(Repository repository, String atAddress, Transaction transaction) throws DataException { + int height = transaction.getHeight(); + byte[] transactionSignature = transaction.getTransactionData().getSignature(); + + BlockData blockData = repository.getBlockRepository().fromHeight(height); + assertNotNull(blockData); + + Block block = new Block(repository, blockData); + + List blockTransactions = block.getTransactions(); + int sequence; + for (sequence = blockTransactions.size() - 1; sequence >= 0; --sequence) + if (Arrays.equals(blockTransactions.get(sequence).getTransactionData().getSignature(), transactionSignature)) + break; + + assertNotSame(-1, sequence); + + byte[] rawLastTxTimestamp = new byte[8]; + extractLastTxTimestamp(repository, atAddress, rawLastTxTimestamp); + + Timestamp expectedTimestamp = new Timestamp(height, sequence); + Timestamp actualTimestamp = new Timestamp(BitTwiddling.longFromBEBytes(rawLastTxTimestamp, 0)); + + assertEquals(String.format("Expected height %d, seq %d but was height %d, seq %d", + height, sequence, + actualTimestamp.blockHeight, actualTimestamp.transactionSequence + ), + expectedTimestamp.longValue(), + actualTimestamp.longValue()); + + byte[] expectedPartialSignature = new byte[24]; + System.arraycopy(transactionSignature, 8, expectedPartialSignature, 0, expectedPartialSignature.length); + + byte[] actualPartialSignature = new byte[24]; + System.arraycopy(rawLastTxTimestamp, 8, actualPartialSignature, 0, actualPartialSignature.length); + + assertArrayEquals(expectedPartialSignature, actualPartialSignature); + } + + private static TestAccount generateTestAccount(Repository repository, String accountName) { + byte[] seed = new byte[32]; + new SecureRandom().nextBytes(seed); + return new TestAccount(repository, accountName, Base58.encode(seed), false); + } + +} From c989e3c41305f2d7024dbf663915a3967b3910e7 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:05:24 +0100 Subject: [PATCH 4/8] Rework trustless manager --- .../crypto/TrustlessSSLSocketFactory.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/qortal/crypto/TrustlessSSLSocketFactory.java b/src/main/java/org/qortal/crypto/TrustlessSSLSocketFactory.java index f14efae8..3643e552 100644 --- a/src/main/java/org/qortal/crypto/TrustlessSSLSocketFactory.java +++ b/src/main/java/org/qortal/crypto/TrustlessSSLSocketFactory.java @@ -1,33 +1,33 @@ package org.qortal.crypto; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.*; import java.security.cert.X509Certificate; public abstract class TrustlessSSLSocketFactory { - // Create a trust manager that does not validate certificate chains + /** + * Creates a SSLSocketFactory that ignore certificate chain validation because ElectrumX servers use mostly + * self signed certificates. + */ private static final TrustManager[] TRUSTLESS_MANAGER = new TrustManager[] { new X509TrustManager() { - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; + public X509Certificate[] getAcceptedIssuers() { + return null; } - - public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + public void checkClientTrusted(X509Certificate[] certs, String authType) { } - - public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; - // Install the all-trusting trust manager + /** + * Install the all-trusting trust manager. + */ private static final SSLContext sc; static { try { - sc = SSLContext.getInstance("TLSv1.3"); + sc = SSLContext.getInstance("SSL"); sc.init(null, TRUSTLESS_MANAGER, new java.security.SecureRandom()); } catch (Exception e) { throw new RuntimeException(e); @@ -37,5 +37,4 @@ public abstract class TrustlessSSLSocketFactory { public static SSLSocketFactory getSocketFactory() { return sc.getSocketFactory(); } - } From 79b674d2f2693c3b769efd3d4cf2ec9fdf406802 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:25:18 +0100 Subject: [PATCH 5/8] Update AT metadata --- lib/org/ciyam/AT/maven-metadata-local.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/org/ciyam/AT/maven-metadata-local.xml b/lib/org/ciyam/AT/maven-metadata-local.xml index d8f3dd34..355c973f 100644 --- a/lib/org/ciyam/AT/maven-metadata-local.xml +++ b/lib/org/ciyam/AT/maven-metadata-local.xml @@ -5,14 +5,11 @@ 1.4.1 - 1.3.4 - 1.3.5 - 1.3.6 1.3.7 1.3.8 1.4.0 1.4.1 - 20230821074325 + 20231212092227 From bf8005aa5a010a1f2fddf2a3e8391f9963416057 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:26:30 +0100 Subject: [PATCH 6/8] Update AT --- lib/org/ciyam/AT/1.4.1/AT-1.4.1.jar | Bin 161850 -> 161856 bytes lib/org/ciyam/AT/1.4.1/AT-1.4.1.pom | 17 ++++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/org/ciyam/AT/1.4.1/AT-1.4.1.jar b/lib/org/ciyam/AT/1.4.1/AT-1.4.1.jar index 05c548c8b59e0ca4254cb43fe5f809fe80a0c83e..20e773a4588153466ae87dd8fea4a3f16d37a371 100644 GIT binary patch delta 8354 zcmZu$30#fY`@iR0ZAzsTX-}JoED=()N}DN__NT|i8R-^GnSM+ zQc`0XO&a_dTO}jgsQ>ex^Opae#^=+g-R3KO1OkCC{Adu}nOHl|#!@+1X^#9g3(xx6Z^qmiCz}^z zB)k9%PwCTN_eOBP@{zd^07N5^CH)yoeyA2F90Y@agDcg>tj7XDg{Z>H zND{Fc5ljW_T$O~}K$5uwrOMDzm<>9G=%UQWrOkD)s0|hwii>Jm=^DwTYiRrcy83~^ zJ~nl17?KexbBcU&Jg2-83IvvN1Qj9!iRWP4%`_Z;g7(spcxPD@TlP=}Ph~v9o$j&0 zw7H{raXWmLX?Zw&Jmb?@_`{`W;N#EnksJ?28F(-$R zi4?4B`Qc&IQ?CBVn^Kg_wZ<-`nSxLEpKCYJBb=9OeJ$4A%DhK4xs@I{zqN>53{tiR^|&OAvy65F%}Xp zO}vb)XzxMtbj7Km=m?`>9UsBIE%ib7SfKUfA$_QCy#7Kzu~CvN+RuDb+8%mi0{G?_ zF;qaqB?^Yfg^Gx`6}B+a^)@%<=yG{myq|5&sn*|LebpCsv3^K5Q(CQrav1FOBeK(E z0XCDm{G~P?!d$-f)%?V!0RlmXJl$)=dkL18xNJr(EbPTfvP^qI>^TOMbvs$C3#uAP zi3eoZmnLM*Xc>gFT_KX&@i(Qnu^G*0Yo1%C|F96&B+?>~HGMf_ci#%9v$YR>gPA^y zfqZhQ*rMkHXufX$X7XP}MgoD|Y!OiAM5?kLZH=^63)OKmn8KOHLnTX43YZ;d1 z9u{0lnZ+_>h1E~)Mj7PeNkDbGMbZY?3{8?R--jlOY$V_5Xh#VR4`DrqXtN{2= z7KS a}mFfF;iqxUT5s}J&9ugFf!QhsL; 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 D8A>g9 diff --git a/lib/org/ciyam/AT/1.4.1/AT-1.4.1.pom b/lib/org/ciyam/AT/1.4.1/AT-1.4.1.pom index 16f644b9..d88a53e2 100644 --- a/lib/org/ciyam/AT/1.4.1/AT-1.4.1.pom +++ b/lib/org/ciyam/AT/1.4.1/AT-1.4.1.pom @@ -10,14 +10,13 @@ UTF-8 false - - 3.8.1 - 3.2.0 - 3.3.1 - 3.0.0-M4 - 3.2.0 - - 1.64 + 1.69 + 4.13.2 + 3.11.0 + 3.3.0 + 3.6.3 + 3.3.0 + 3.2.2 @@ -117,7 +116,7 @@ junit junit - 4.13 + ${junit.version} test From 87b3b037bdc2938243e9c62c27a29c9ebb00b40e Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:20:30 +0100 Subject: [PATCH 7/8] Update dependencies --- pom.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index b64917f4..4d736704 100644 --- a/pom.xml +++ b/pom.xml @@ -10,18 +10,18 @@ 7dc8c6f 0.15.10 1.69 - 3.4.0 + 3.5.0 ${maven.build.timestamp} 1.4.1 3.8.0 1.11.0 2.11.0 - 1.24.0 - 3.13.0 + 1.25.0 + 3.14.0 1.2.2 0.12.3 4.9.10 - 1.59.0 + 1.60.0 32.1.3-jre 2.2 1.2.1 @@ -34,7 +34,7 @@ 9.4.53.v20231009 1.1.1 20231013 - 1.16.2 + 1.17.1 5.10.0 1.0.0 2.21.1 @@ -46,15 +46,15 @@ 3.2.2 1.1.0 UTF-8 - 3.24.4 + 3.25.0 1.5.3 0.16 1.17 1.7.36 2.0.10 - 5.9.0 + 5.10.3 1.2 - 2.16.1 + 2.16.2 1.9 From 5afa4e5b1ad38fa962da1204c4e768b09990c731 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:05:08 +0100 Subject: [PATCH 8/8] Default minPeerVersion set to 4.4.0 --- src/main/java/org/qortal/settings/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/qortal/settings/Settings.java b/src/main/java/org/qortal/settings/Settings.java index ba90208b..29c726b1 100644 --- a/src/main/java/org/qortal/settings/Settings.java +++ b/src/main/java/org/qortal/settings/Settings.java @@ -221,7 +221,7 @@ public class Settings { public long recoveryModeTimeout = 9999999999999L; /** Minimum peer version number required in order to sync with them */ - private String minPeerVersion = "4.3.2"; + private String minPeerVersion = "4.4.0"; /** Whether to allow connections with peers below minPeerVersion * If true, we won't sync with them but they can still sync with us, and will show in the peers list * If false, sync will be blocked both ways, and they will not appear in the peers list */