diff --git a/build.sbt b/build.sbt index 6486ba2219..4090fcd3d8 100644 --- a/build.sbt +++ b/build.sbt @@ -272,10 +272,8 @@ lazy val ergoCore = (project in file("ergo-core")) commonSettings, name := "ergo-core", libraryDependencies ++= Seq( - "com.typesafe.akka" %% "akka-actor" % akkaVersion, "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, "com.iheart" %% "ficus" % ficusVersion, - "com.github.ben-manes.caffeine" % "caffeine" % "2.9.3", // use 3.x only for java 11+ effectiveSigma, (effectiveSigma % Test).classifier("tests") ), diff --git a/ergo-core/src/test/resources/application.conf b/ergo-core/src/test/resources/application.conf deleted file mode 100644 index f64e12486a..0000000000 --- a/ergo-core/src/test/resources/application.conf +++ /dev/null @@ -1,209 +0,0 @@ -ergo { - # Directory to keep data - directory = ${user.dir}"/.ergo_test/data" - - networkType = "testnet" - - # Settings for node view holder regime. See papers.yellow.ModifiersProcessing.md - node { - # State type. Possible options are: - # "utxo" - keep full utxo set, that allows to validate arbitrary block and generate ADProofs - # "digest" - keep state root hash only and validate transactions via ADProofs - stateType = "utxo" - - # Download block transactions and verify them (requires BlocksToKeep == 0 if disabled) - verifyTransactions = true - - # Number of last blocks to keep with transactions and ADproofs, for all other blocks only header will be stored. - # Keep all blocks from genesis if negative - blocksToKeep = 1000 - - # Download PoPoW proof on node bootstrap - popowBootstrap = false - - # Minimal suffix size for PoPoW proof (may be pre-defined constant or settings parameter) - popowSuffix = 10 - - # Is the node is doing mining - mining = true - - # maximum cost of transaction for it to not be considered malicious - maxTransactionCost = 1000000 - - useExternalMiner = false - - # Public key mining rewards will be dedicated to - miningPubKeyHex = null - - # If true, a node generates blocks being offline. The only really useful case for it probably is to start a new - # blockchain - offlineGeneration = false - - # Interval of polling for a candidate - internalMinerPollingInterval = 1s - - mempoolCapacity = 100000 - - mempoolCleanupDuration = 10s - - mempoolSorting = "bySize" - - # Number of transactions from mempool to be re-broadcasted at each epoch - rebroadcastCount = 3 - - # Minimal fee amount of transactions mempool accepts - minimalFeeAmount = 0 - - # A node is considering that the chain is synced if sees a block header with timestamp no more - # than headerChainDiff blocks on average from future - # for tests, the value is 100 (as in mainnet) - headerChainDiff = 100 - - # Dump ADProofs only for the suffix given during bootstrapping - adProofsSuffixLength = 114688 // 112k - } - - cache { - history { - # Number of recently used block sections that will be kept in memory - blockSectionsCacheSize = 12 - - # Number of recently used headers that will be kept in memory - headersCacheSize = 100 - - # Number of recently used indexes that will be kept in memory - indexesCacheSize = 1000 - } - network { - # Maximum number of invalid modifiers in bloom filters - invalidModifiersBloomFilterCapacity = 10000000 - - # Non-zero fraction of 1 as a rate of element expiration when capacity is full, the lower the more gradual expiration. - # example : 0.1 is represented as 10 bloom filters expiring one by one - invalidModifiersBloomFilterExpirationRate = 0.1 - - # Maximum number of invalid modifiers to keep in cache, following modifiers are kept in bloom filters - invalidModifiersCacheSize = 10000 - - # For how long to keep invalid modifiers in cache - invalidModifiersCacheExpiration = 6h - } - mempool { - # Maximum number of invalid modifiers in bloom filters - invalidModifiersBloomFilterCapacity = 10000000 - - # Non-zero fraction of 1 as a rate of element expiration when capacity is full, the lower the more gradual expiration. - # example : 0.1 is represented as 10 bloom filters expiring one by one - invalidModifiersBloomFilterExpirationRate = 0.1 - - # Maximum number of invalid modifiers to keep in cache, following modifiers are kept in bloom filters - invalidModifiersCacheSize = 10000 - - # For how long to keep invalid modifiers in cache - invalidModifiersCacheExpiration = 6h - } - } - - #Chain-specific settings. Change only if you are going to launch a new chain! - chain { - - genesisId = null - - monetary { - # delay between the block mined and a time, when the reward can be spent. ~ 1 day. - minerRewardDelay = -1000 - } - - # Public keys of founders for tests. Two keys from defaultProver and one random one. - foundersPubkeys = [ - "038b0f29a60fa8d7e1aeafbe512288a6c6bc696547bbf8247db23c95e83014513c", - "031ee1ab3b729f21e0dcee05642a63745286354d8e511e6376838e235a28078c01", - "0248502b73f35bb2b77eb5ad16f80f55beff178ccd104488edd2d8b69c192c109d" - ] - - # Base16 representation of genesis state roothash - genesisStateDigestHex = "93914ecff82cea3b53b32d0f0527069f7361ef3b426271235eb6f4d76337900202" - - # Network address prefix, currently reserved values are 0x00 (money chain mainnet) and 0x10 (16 in decimal, - # money chain testnet) - addressPrefix = 16 - - # Desired time interval between blocks - blockInterval = 1m - - # Difficulty network start with - initialDifficultyHex = "01" - - # length of an epoch in difficulty recalculation - epochLength = 100 - - //Proof-of-Work algorithm and its parameters. Possible options are "fake" and "autolykos". - powScheme { - powType = "fake" - } - - makeSnapshotEvery = 128 - } - - wallet { - - secretStorage { - - secretDir = ${ergo.directory}"/wallet/keystore" - - encryption { - - # Pseudo-random function with output of length `dkLen` (PBKDF2 param) - prf = "HmacSHA256" - - # Number of PBKDF2 iterations (PBKDF2 param) - c = 128000 - - # Desired bit-length of the derived key (PBKDF2 param) - dkLen = 256 - } - - } - - # Generating seed length in bits - # Options: 128, 160, 192, 224, 256 - seedStrengthBits = 160 - - # Language to be used in mnemonic seed - # Options: "chinese_simplified", "chinese_traditional", "english", "french", "italian", "japanese", "korean", "spanish" - mnemonicPhraseLanguage = "english" - - defaultTransactionFee = 10000 - - # Boxes with value smaller than dustLimit are disregarded in wallet scan logic - dustLimit = 999 - - # Save used boxes (may consume additinal disk space) or delete them immediately - keepSpentBoxes = false - - # Mnemonic seed used in wallet for tests - testMnemonic = "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic" - - # Number of keys to be generated for tests - testKeysQty = 5 - } - -} - -scorex { - restApi { - apiKeyHash = null - publicUrl = "https://example.com:80" - } -} - - -akka { - test { - timefactor = 3 # duration scale factor to prevent spurious test failures on the heavily loaded CI servers - } - # Don't terminate ActorSystem via CoordinatedShutdown in tests - coordinated-shutdown.terminate-actor-system = off - coordinated-shutdown.run-by-actor-system-terminate = off - coordinated-shutdown.run-by-jvm-shutdown-hook = off -} diff --git a/ergo-core/src/test/resources/difficulty.csv b/ergo-core/src/test/resources/difficulty.csv deleted file mode 100644 index b91f7bbc0e..0000000000 --- a/ergo-core/src/test/resources/difficulty.csv +++ /dev/null @@ -1,30209 +0,0 @@ -height,timestamp,requiredDifficulty -0,1512376702808,1 -1,1512376710654,1 -2,1512376717432,1 -3,1512376724339,1 -4,1512376728328,1 -5,1512376732220,1 -6,1512376736177,1 -7,1512376740239,1 -8,1512376744176,1 -9,1512376748188,1 -10,1512376752090,1 -11,1512376755962,1 -12,1512376759932,1 -13,1512376763919,1 -14,1512376767935,1 -15,1512376771852,1 -16,1512376775927,1 -17,1512376779911,1 -18,1512376783860,1 -19,1512376787761,1 -20,1512376791808,1 -21,1512376795699,1 -22,1512376799555,1 -23,1512376803585,1 -24,1512376807568,1 -25,1512376811411,1 -26,1512376816170,1 -27,1512376820230,1 -28,1512376928330,1 -29,1512376934622,1 -30,1512376939460,1 -31,1512376943403,1 -32,1512376947512,1 -33,1512376951541,1 -34,1512376955546,1 -35,1512376959564,1 -36,1512376963639,1 -37,1512376967580,1 -38,1512376971575,1 -39,1512376975547,1 -40,1512376979559,1 -41,1512376983535,1 -42,1512376988400,1 -43,1512376992096,1 -44,1512376996156,1 -45,1512377000125,1 -46,1512377004064,1 -47,1512377007974,1 -48,1512377011880,1 -49,1512377015762,1 -50,1512377019740,1 -51,1512377024191,1 -52,1512377028141,1 -53,1512377032070,1 -54,1512377036014,1 -55,1512377039969,1 -56,1512377043907,1 -57,1512377047826,1 -58,1512377051671,1 -59,1512377056107,1 -60,1512377059990,1 -61,1512377063895,1 -62,1512377067814,1 -63,1512377071710,1 -64,1512377075693,1 -65,1512377079857,1 -66,1512377083788,1 -67,1512377087710,1 -68,1512377091621,1 -69,1512377095570,1 -70,1512377100010,1 -71,1512377104491,1 -72,1512377108678,1 -73,1512377115336,1 -74,1512377119269,1 -75,1512377126164,1 -76,1512377130094,1 -77,1512377134546,1 -78,1512377138473,1 -79,1512377142365,1 -80,1512377146328,1 -81,1512377150225,1 -82,1512377154212,1 -83,1512377161021,1 -84,1512377165104,1 -85,1512377171793,1 -86,1512377175731,1 -87,1512377179652,1 -88,1512377183568,1 -89,1512377187518,1 -90,1512377191454,1 -91,1512377195549,1 -92,1512377199497,1 -93,1512377203366,1 -94,1512377207321,1 -95,1512377214132,1 -96,1512377218034,1 -97,1512377221973,1 -98,1512377226221,1 -99,1512377230160,1 -100,1512377234090,1 -101,1512377238006,13 -102,1512377253487,20 -103,1512377272207,22 -104,1512377296486,24 -105,1512377303341,26 -106,1512377328053,34 -107,1512379794273,37 -108,1512379875509,36 -109,1512380096763,36 -110,1512380110870,35 -111,1512380183985,42 -112,1512380247017,43 -113,1512380307408,43 -114,1512380402090,43 -115,1512380640913,43 -116,1512380699580,42 -117,1512380731056,43 -118,1512380773113,45 -119,1512380828976,47 -120,1512380849902,48 -121,1512380948176,53 -122,1512381015071,52 -123,1512381056122,53 -124,1512381224581,54 -125,1512381470518,54 -126,1512381565769,53 -127,1512381587092,53 -128,1512381634900,58 -129,1512381659183,59 -130,1512381718624,63 -131,1512381775798,65 -132,1512381929226,65 -133,1512381959161,65 -134,1512382079796,69 -135,1512382265782,68 -136,1512382306708,67 -137,1512382416888,70 -138,1512382488190,69 -139,1512382517772,69 -140,1512382698363,73 -141,1512382804251,72 -142,1512382951735,73 -143,1512382962084,72 -144,1512382980407,86 -145,1512382987879,96 -146,1512383175798,124 -147,1512383189916,123 -148,1512383231195,141 -149,1512383584870,147 -150,1512383715201,144 -151,1512383761593,143 -152,1512383955938,148 -153,1512384163159,146 -154,1512384340686,144 -155,1512384573829,143 -156,1512384880262,141 -157,1512385078230,138 -158,1512385216690,137 -159,1512385393268,136 -160,1512385521442,135 -161,1512385603247,134 -162,1512385732154,134 -163,1512385813822,132 -164,1512385833400,133 -165,1512386065649,146 -166,1512386149061,143 -167,1512386198044,143 -168,1512386442829,147 -169,1512386548732,144 -170,1512387029948,144 -171,1512387040002,140 -172,1512387262252,169 -173,1512387389646,167 -174,1512387647248,164 -175,1512388234899,162 -176,1512388458448,157 -177,1512388466008,155 -178,1512389172537,199 -179,1512389729013,194 -180,1512390062663,190 -181,1512390179091,185 -182,1512390703660,185 -183,1512390757180,179 -184,1512391094809,182 -185,1512391449128,178 -186,1512392701770,173 -187,1512392846519,168 -188,1512392964651,165 -189,1512393004889,162 -190,1512393035216,167 -191,1512393210624,174 -192,1512393253838,170 -193,1512393432894,174 -194,1512393528564,170 -195,1512393672846,168 -196,1512393781623,164 -197,1512394331616,162 -198,1512394346138,157 -199,1512394623139,176 -200,1512394787236,170 -201,1512394967251,167 -202,1512394978109,165 -203,1512395243253,197 -204,1512395336415,192 -205,1512395430865,191 -206,1512395569241,193 -207,1512396103876,191 -208,1512396501632,184 -209,1512397128525,178 -210,1512397307764,171 -211,1512397625277,169 -212,1512397668726,164 -213,1512399122295,167 -214,1512399166932,159 -215,1512399464577,160 -216,1512399624673,154 -217,1512399935645,150 -218,1512400583173,145 -219,1512400685184,139 -220,1512400718966,136 -221,1512400831848,141 -222,1512401066067,137 -223,1512401137712,132 -224,1512401161613,130 -225,1512401214219,135 -226,1512401570074,135 -227,1512402084183,128 -228,1512402197199,125 -229,1512402354842,121 -230,1512402629700,118 -231,1512402972920,112 -232,1512402988542,106 -233,1512403820885,116 -234,1512458304892,111 -235,1512458864155,104 -236,1512458910949,96 -237,1512458972974,96 -238,1512459063261,92 -239,1512459081039,88 -240,1512459149627,95 -241,1512459174348,90 -242,1512459325602,92 -243,1512459379328,85 -244,1512459415232,90 -245,1512459435076,93 -246,1512459685910,113 -247,1512459774830,107 -248,1512459971221,113 -249,1512460056453,111 -250,1512460066731,108 -251,1512460290384,126 -252,1512460377195,124 -253,1512460461812,122 -254,1512460529906,118 -255,1512460711200,116 -256,1512460995832,111 -257,1512461316902,105 -258,1512461442790,99 -259,1512461524475,94 -260,1512461606197,90 -261,1512461821261,87 -262,1512461838770,82 -263,1512461865205,86 -264,1512461920316,89 -265,1512462101346,94 -266,1512462461697,88 -267,1512462467447,83 -268,1512462626554,114 -269,1512463472231,108 -270,1512464239625,102 -271,1512464334653,95 -272,1512464433864,107 -273,1512464857940,103 -274,1512465017261,98 -275,1512465399571,93 -276,1512466482393,86 -277,1512467473832,80 -278,1512468026867,98 -279,1512487875104,92 -280,1512488003896,86 -281,1512488022209,82 -282,1512488096062,88 -283,1512488436839,85 -284,1512488495191,82 -285,1512488515213,80 -286,1512488653765,84 -287,1512488766603,78 -288,1512488878103,74 -289,1512488939726,71 -290,1512488982106,72 -291,1512489154149,77 -292,1512489182748,73 -293,1512489214778,77 -294,1512489245226,77 -295,1512489314703,79 -296,1512489337370,76 -297,1512489641088,80 -298,1512489931149,75 -299,1512492427170,82 -300,1512492507174,76 -301,1512494254981,73 -302,1512494306451,68 -303,1512494417876,85 -304,1512494540707,82 -305,1512494598585,80 -306,1512494662335,80 -307,1512494740838,79 -308,1512495091393,77 -309,1512495495971,72 -310,1512496344448,68 -311,1512496630012,64 -312,1512496743642,60 -313,1512496851903,59 -314,1512497062602,56 -315,1512497113445,55 -316,1512497311410,53 -317,1512497326593,49 -318,1512497442286,53 -319,1512497500767,49 -320,1512497627777,47 -321,1512497736897,47 -322,1512497835899,45 -323,1512497919947,41 -324,1512498017360,39 -325,1512498075810,42 -326,1512498219549,42 -327,1512498322606,38 -328,1512498449993,35 -329,1512498523665,31 -330,1512498566822,28 -331,1512498598583,26 -332,1512498655322,23 -333,1512498799352,28 -334,1512498806267,24 -335,1512498849886,27 -336,1512498904793,24 -337,1512498912968,23 -338,1512498978317,27 -339,1512498994248,25 -340,1512499027307,29 -341,1512499067828,29 -342,1512499128507,30 -343,1512499203773,27 -344,1512499207722,26 -345,1512499330939,40 -346,1512499387166,42 -347,1512499417108,40 -348,1512499494973,40 -349,1512499620427,38 -350,1512499704750,35 -351,1512499805896,45 -352,1512499860224,42 -353,1512499871074,42 -354,1512499904799,49 -355,1512500103923,51 -356,1512500124571,48 -357,1512500170697,50 -358,1512500254470,49 -359,1512500322846,47 -360,1512500499014,46 -361,1512500706343,44 -362,1512500739374,40 -363,1512500798767,45 -364,1512501154392,47 -365,1512501417124,45 -366,1512501429988,42 -367,1512501474558,47 -368,1512501505585,62 -369,1512501566421,64 -370,1512501611738,63 -371,1512501624492,63 -372,1512501775277,73 -373,1512501875606,73 -374,1512501939481,69 -375,1512502018809,69 -376,1512502030744,68 -377,1512502037346,79 -378,1512502196206,104 -379,1512502246876,101 -380,1512502341931,101 -381,1512502559174,100 -382,1512502793321,102 -383,1512502854013,100 -384,1512502876202,101 -385,1512502995108,109 -386,1512503178349,111 -387,1512503184979,109 -388,1512503189269,145 -389,1512503217084,221 -390,1512503291289,236 -391,1512503469587,240 -392,1512503914938,237 -393,1512504029263,234 -394,1512504225082,235 -395,1512505047193,235 -396,1512505188486,231 -397,1512505419819,233 -398,1512505797574,229 -399,1512505959982,224 -400,1512507277787,221 -401,1512507324869,217 -402,1512507332475,221 -403,1512507551193,286 -404,1512507620188,283 -405,1512507628194,286 -406,1512508024076,365 -407,1512508063223,360 -408,1512508350624,375 -409,1512508992973,369 -410,1512509566808,361 -411,1512509857420,354 -412,1512511132041,348 -413,1512511403903,340 -414,1512511411233,334 -415,1512511891477,434 -416,1512512755692,426 -417,1512512856141,417 -418,1512513295968,420 -419,1512513577817,412 -420,1512514193824,405 -421,1512514893284,397 -422,1512515231118,388 -423,1512515484375,379 -424,1512515966461,373 -425,1512516142148,364 -426,1512517216694,359 -427,1512517298738,348 -428,1512517527972,348 -429,1512518728049,341 -430,1512518975274,330 -431,1512519382942,323 -432,1512519744440,314 -433,1512521958323,306 -434,1512523591163,295 -435,1512523866717,288 -436,1512524328418,280 -437,1512524535268,271 -438,1512524687222,266 -439,1512525148378,259 -440,1512525450766,251 -441,1512525869862,243 -442,1512526509332,234 -443,1512526542284,224 -444,1512526734150,230 -445,1512526784201,229 -446,1512527351400,229 -447,1512527489872,220 -448,1512528173588,213 -449,1512528210608,203 -450,1512528545893,205 -451,1512528817177,195 -452,1512529121145,186 -453,1512530127674,177 -454,1512531147750,171 -455,1512531271817,161 -456,1512531902544,153 -457,1512532007011,146 -458,1512532062456,139 -459,1512532435215,134 -460,1512532573747,124 -461,1512532869309,114 -462,1512532900231,104 -463,1512533205858,102 -464,1512533327972,92 -465,1512533427587,83 -466,1512533840566,73 -467,1512534341716,66 -468,1512534398577,56 -469,1512534548234,50 -470,1512534569387,40 -471,1512534593905,35 -472,1512534734625,34 -473,1512534886663,23 -474,1512535029547,13 -475,1512535068986,4 -476,1512535089183,1 -477,1512535119719,1 -478,1512535137488,1 -479,1512535154132,1 -480,1512535170950,1 -481,1512535197279,1 -482,1512535214967,1 -483,1512535228522,1 -484,1512535256454,1 -485,1512535270372,1 -486,1512535284915,1 -487,1512535304246,1 -488,1512535332702,1 -489,1512535349387,1 -490,1512535370730,1 -491,1512535390581,1 -492,1512535438794,1 -493,1512535474944,1 -494,1512535501972,1 -495,1512535557013,1 -496,1512535576032,1 -497,1512535596332,1 -498,1512535607604,1 -499,1512535624005,1 -500,1512535641003,1 -501,1512535649075,1 -502,1512535655810,1 -503,1512535663358,1 -504,1512535669728,1 -505,1512535676989,1 -506,1512535683785,1 -507,1512535696189,1 -508,1512535703333,1 -509,1512535710044,1 -510,1512535717402,1 -511,1512535724142,1 -512,1512535731647,1 -513,1512535738689,1 -514,1512535752088,1 -515,1512535759417,1 -516,1512535765817,1 -517,1512535773314,1 -518,1512535780495,1 -519,1512535793525,1 -520,1512535799886,1 -521,1512535806662,1 -522,1512535813857,1 -523,1512535820652,1 -524,1512535827468,1 -525,1512535834216,1 -526,1512535841044,1 -527,1512535847909,1 -528,1512535860406,1 -529,1512535867219,1 -530,1512535879904,1 -531,1512535886504,1 -532,1512535893489,1 -533,1512535900416,1 -534,1512535907437,1 -535,1512535913682,1 -536,1512535926135,1 -537,1512535934104,1 -538,1512535941206,1 -539,1512535948649,1 -540,1512535955907,1 -541,1512535963638,1 -542,1512535976705,1 -543,1512535983099,1 -544,1512535990407,1 -545,1512535996473,1 -546,1512536003205,1 -547,1512536009500,1 -548,1512536016298,1 -549,1512536023322,1 -550,1512536029590,1 -551,1512536041397,1 -552,1512536048849,1 -553,1512536055591,1 -554,1512536061967,1 -555,1512536068417,1 -556,1512536074778,1 -557,1512536082030,1 -558,1512536088878,1 -559,1512536095480,1 -560,1512536107430,1 -561,1512536114004,1 -562,1512536120910,1 -563,1512536127450,2 -564,1512536134552,4 -565,1512536152452,5 -566,1512536159490,6 -567,1512536189801,8 -568,1512536214119,8 -569,1512536248653,9 -570,1512536266210,8 -571,1512536273365,12 -572,1512536329498,18 -573,1512536377535,19 -574,1512536536609,19 -575,1512536560837,19 -576,1512536573243,20 -577,1512536662489,24 -578,1512536669748,24 -579,1512536816603,31 -580,1512537035121,31 -581,1512537284829,30 -582,1512537317214,30 -583,1512537358857,31 -584,1512537510776,33 -585,1512537535872,32 -586,1512537549211,35 -587,1512537782607,40 -588,1512538223229,39 -589,1512538237452,39 -590,1512538597625,45 -591,1512538616387,44 -592,1512538671449,48 -593,1512538876287,49 -594,1512539130146,48 -595,1512539159717,47 -596,1512539314274,50 -597,1512539357705,50 -598,1512539491061,52 -599,1512539546390,52 -600,1512539680632,52 -601,1512539723789,52 -602,1512539731153,54 -603,1512539779578,70 -604,1512539831462,72 -605,1512539958141,74 -606,1512540120218,73 -607,1512540249747,73 -608,1512540435427,73 -609,1512540528182,72 -610,1512540954317,72 -611,1512541715158,71 -612,1512542086199,70 -613,1512542187357,68 -614,1512542561951,68 -615,1512543210561,67 -616,1512543637180,65 -617,1512543781357,64 -618,1512543825419,63 -619,1512544109254,65 -620,1512544148978,64 -621,1512544414732,66 -622,1512544523952,65 -623,1512544591298,64 -624,1512544801098,64 -625,1512545339876,64 -626,1512545412009,62 -627,1512545929329,63 -628,1512546388559,60 -629,1512546763934,59 -630,1512547051225,57 -631,1512547300485,56 -632,1512547626987,55 -633,1512548220327,53 -634,1512548639262,52 -635,1512548666413,50 -636,1512548769928,53 -637,1512548961609,51 -638,1512549224802,50 -639,1512549423311,49 -640,1512549582141,47 -641,1512549835658,46 -642,1512549868600,44 -643,1512550399590,45 -644,1512550455361,44 -645,1512550577040,43 -646,1512551122603,43 -647,1512551129892,40 -648,1512551339801,52 -649,1512551415302,50 -650,1512551498270,49 -651,1512551819281,48 -652,1512551990991,46 -653,1512552138227,44 -654,1512552366760,42 -655,1512552391240,40 -656,1512552475891,42 -657,1512552696369,41 -658,1512552846620,40 -659,1512552917426,38 -660,1512552972926,37 -661,1512553260743,36 -662,1512553492791,33 -663,1512553735976,32 -664,1512553913798,30 -665,1512553955106,28 -666,1512553979638,28 -667,1512554275827,29 -668,1512554324251,27 -669,1512554508871,26 -670,1512554666138,24 -671,1512554823719,22 -672,1512555002937,23 -673,1512555069784,20 -674,1512555123292,19 -675,1512555158872,17 -676,1512555227536,17 -677,1512555257692,17 -678,1512555274063,17 -679,1512555281395,21 -680,1512555300458,25 -681,1512555334056,26 -682,1512555386333,25 -683,1512555454482,26 -684,1512555639445,24 -685,1512555815284,22 -686,1512555866834,22 -687,1512556140741,23 -688,1512556296508,22 -689,1512556692578,19 -690,1512557130201,21 -691,1512557197221,18 -692,1512557251748,20 -693,1512557305501,19 -694,1512557370608,19 -695,1512557436546,17 -696,1512557504851,18 -697,1512557527956,17 -698,1512557564107,18 -699,1512557612748,18 -700,1512557619766,17 -701,1512557680664,21 -702,1512557729717,22 -703,1512557844439,29 -704,1512558247774,30 -705,1512558260947,29 -706,1512558477900,34 -707,1512558899449,34 -708,1512559033646,31 -709,1512559413510,30 -710,1512559709204,30 -711,1512559896694,29 -712,1512560112080,28 -713,1512560173030,27 -714,1512560204925,27 -715,1512560425039,27 -716,1512560672967,26 -717,1512560679923,24 -718,1512561115371,31 -719,1512561662901,30 -720,1512561794263,29 -721,1512561948868,29 -722,1512562042692,29 -723,1512562208869,29 -724,1512562322577,28 -725,1512562385947,27 -726,1512562448367,27 -727,1512562589988,27 -728,1512562598150,26 -729,1512562651718,32 -730,1512562832048,30 -731,1512563027460,31 -732,1512563071270,30 -733,1512563111550,29 -734,1512563204108,29 -735,1512563319435,28 -736,1512563359448,29 -737,1512563384787,29 -738,1512563416967,30 -739,1512563763455,31 -740,1512563900615,30 -741,1512565185585,28 -742,1512565379792,27 -743,1512565410123,27 -744,1512565436876,27 -745,1512565540048,28 -746,1512565671385,27 -747,1512565775518,27 -748,1512565816619,32 -749,1512565882370,33 -750,1512566006490,33 -751,1512566042077,32 -752,1512566125345,32 -753,1512566222914,31 -754,1512566298643,30 -755,1512566412589,30 -756,1512566531464,32 -757,1512566691529,31 -758,1512566867683,29 -759,1512567086161,28 -760,1512567284192,28 -761,1512639141123,27 -762,1512639167140,26 -763,1512639205457,27 -764,1512639222716,27 -765,1512639398175,29 -766,1512639595440,28 -767,1512639701448,28 -768,1512639749907,27 -769,1512639793593,28 -770,1512639839392,28 -771,1512639860073,27 -772,1512639864996,29 -773,1512639881503,41 -774,1512639977759,46 -775,1512640127745,45 -776,1512640176930,44 -777,1512640197991,44 -778,1512640452491,48 -779,1512640812346,48 -780,1512641182069,49 -781,1512641509243,49 -782,1512641581105,49 -783,1512641599163,49 -784,1512641617255,53 -785,1512642473780,59 -786,1512642515397,57 -787,1512642532067,58 -788,1512642846035,65 -789,1512643164703,63 -790,1512643363048,61 -791,1512643379546,59 -792,1512643477461,66 -793,1512643494225,65 -794,1512643666018,73 -795,1512643960473,71 -796,1512644012256,69 -797,1512644215647,70 -798,1512644373025,69 -799,1512644413338,68 -800,1512644433787,71 -801,1512644678190,79 -802,1512644742855,78 -803,1512644837531,78 -804,1512644944367,78 -805,1512645037630,76 -806,1512645095922,79 -807,1512645147135,79 -808,1512645617887,80 -809,1512645792421,78 -810,1512645829401,76 -811,1512645838128,78 -812,1512645963248,97 -813,1512646003333,96 -814,1512646137056,99 -815,1512646272298,98 -816,1512646418027,97 -817,1512646477143,95 -818,1512646606721,100 -819,1512646710029,98 -820,1512646718849,98 -821,1512646723708,121 -822,1512646739965,177 -823,1512646994144,199 -824,1512647112924,196 -825,1512647269913,195 -826,1512648302951,193 -827,1512648464081,189 -828,1512648975612,188 -829,1512649677788,187 -830,1512649782738,183 -831,1512649877464,182 -832,1512650173941,182 -833,1512651005986,179 -834,1512651072855,175 -835,1512651267408,177 -836,1512651562939,174 -837,1512651807355,171 -838,1512651869610,169 -839,1512652317056,172 -840,1512652458347,167 -841,1512652467117,164 -842,1512652588029,204 -843,1512652639658,202 -844,1512654613444,206 -845,1512654629948,202 -846,1512654860411,226 -847,1512654903708,221 -848,1512655760142,227 -849,1512656602947,222 -850,1512657358576,217 -851,1512657635689,211 -852,1512658153591,207 -853,1512658566669,201 -854,1512658586699,197 -855,1512658860776,214 -856,1512659226399,208 -857,1512659841235,203 -858,1512660381066,197 -859,1512725284693,190 -860,1512725683635,183 -861,1512725764251,178 -862,1512726235899,176 -863,1512726306006,170 -864,1512726370634,170 -865,1512727362440,171 -866,1512727531219,164 -867,1512728148684,159 -868,1512729043485,152 -869,1512729936889,147 -870,1512730081878,140 -871,1512730284491,136 -872,1512730925040,132 -873,1512730944241,132 -874,1512731615233,145 -875,1512731645258,138 -876,1512732253610,143 -877,1512732720629,137 -878,1512733568488,133 -879,1512733587059,125 -880,1512733805736,135 -881,1512734201939,128 -882,1512734519647,122 -883,1512735478451,117 -884,1512735690117,112 -885,1512736783607,110 -886,1512737000092,103 -887,1512737375509,98 -888,1512737763714,95 -889,1512737988739,89 -890,1512738175411,83 -891,1512738403681,77 -892,1512738468520,74 -893,1512738916233,72 -894,1512739028281,69 -895,1512739035251,64 -896,1512739125197,79 -897,1512739226177,76 -898,1512739256883,70 -899,1512739292999,69 -900,1512739841214,68 -901,1512739859933,66 -902,1512740212358,67 -903,1512740312347,61 -904,1512740377991,57 -905,1512740467168,52 -906,1512740491477,47 -907,1512740602517,46 -908,1512740738566,41 -909,1512740745639,35 -910,1512741127218,40 -911,1512741163045,35 -912,1512741466238,41 -913,1512741773610,36 -914,1512741791906,31 -915,1512741869050,29 -916,1512741905286,24 -917,1512741971781,19 -918,1512741990876,15 -919,1512742103852,11 -920,1512742197739,5 -921,1512742263015,11 -922,1512742275489,36 -923,1512742282342,50 -924,1512742490633,64 -925,1512742538545,61 -926,1512742568656,60 -927,1512742628304,60 -928,1512742710206,57 -929,1512742845371,54 -930,1512743138616,49 -931,1512743198457,46 -932,1512743411229,45 -933,1512743435557,40 -934,1512743754203,39 -935,1512743796108,36 -936,1512743884375,35 -937,1512744118018,30 -938,1512744363457,27 -939,1512744376589,24 -940,1512744501136,23 -941,1512744547192,20 -942,1512744589192,38 -943,1512744625586,39 -944,1512744673316,41 -945,1512744796306,38 -946,1512744838956,49 -947,1512745370166,49 -948,1512745481976,52 -949,1512745518329,49 -950,1512745872239,48 -951,1512745995180,45 -952,1512746252020,43 -953,1512746299658,39 -954,1512746329820,37 -955,1512746466410,49 -956,1512746538052,46 -957,1512746736705,45 -958,1512746761047,42 -959,1512746791300,43 -960,1512746850919,43 -961,1512746857702,41 -962,1512746910933,54 -963,1512747312066,54 -964,1512747934845,53 -965,1512748296071,52 -966,1512748360744,49 -967,1512748426195,48 -968,1512748438985,46 -969,1512748655485,51 -970,1512748819762,48 -971,1512748952162,46 -972,1512748977296,44 -973,1512748990127,44 -974,1512749414571,57 -975,1512749469472,53 -976,1512749540412,58 -977,1512749699132,56 -978,1512749735927,53 -979,1512749894001,53 -980,1512750133073,59 -981,1512750215919,56 -982,1512750269158,54 -983,1512750415365,54 -984,1512750987740,52 -985,1512751717102,48 -986,1512751884300,45 -987,1512751913449,43 -988,1512752077776,43 -989,1512752471164,40 -990,1512752507505,37 -991,1512752640035,37 -992,1512752678908,34 -993,1512752775398,34 -994,1512752780968,31 -995,1512752814809,41 -996,1512752873046,52 -997,1512753002794,52 -998,1512753498464,51 -999,1512753627404,50 -1000,1512754058592,49 -1001,1512754123877,47 -1002,1512754203338,49 -1003,1512754359381,48 -1004,1512754394068,45 -1005,1512754409676,46 -1006,1512754534591,51 -1007,1512754601329,51 -1008,1512754649417,50 -1009,1512754673929,49 -1010,1512754759688,57 -1011,1512754769844,55 -1012,1512755016190,66 -1013,1512755064705,64 -1014,1512755190021,63 -1015,1512755398297,63 -1016,1512755487051,61 -1017,1512755549550,59 -1018,1512755635049,58 -1019,1512755728237,57 -1020,1512756015027,56 -1021,1512756035393,53 -1022,1512756216470,56 -1023,1512756327870,57 -1024,1512756664661,64 -1025,1512756749371,61 -1026,1512756826206,62 -1027,1512756904284,63 -1028,1512756999522,62 -1029,1512757029077,62 -1030,1512757081727,64 -1031,1512757230481,64 -1032,1512757263424,62 -1033,1512757293779,64 -1034,1512757384680,67 -1035,1512757509086,66 -1036,1512757645447,65 -1037,1512757729747,63 -1038,1512757979460,62 -1039,1512757999525,60 -1040,1512758263456,65 -1041,1512758461350,63 -1042,1512758519205,61 -1043,1512758663635,60 -1044,1512758723539,59 -1045,1512758801326,60 -1046,1512758917415,58 -1047,1512758964541,57 -1048,1512759219273,57 -1049,1512759337057,55 -1050,1512759351896,54 -1051,1512759515203,58 -1052,1512759528535,57 -1053,1512759747383,65 -1054,1512759813181,61 -1055,1512759936059,61 -1056,1512760060207,59 -1057,1512760202641,58 -1058,1512760400582,56 -1059,1512760417090,55 -1060,1512760510382,60 -1061,1512760653210,60 -1062,1512760683758,65 -1063,1512760708344,68 -1064,1512760886813,71 -1065,1512761141615,69 -1066,1512761189711,66 -1067,1512761200075,66 -1068,1512761278510,79 -1069,1512761391285,82 -1070,1512761568225,80 -1071,1512761793696,77 -1072,1512761883114,76 -1073,1512761946014,76 -1074,1512762147355,79 -1075,1512762172024,76 -1076,1512762349022,81 -1077,1512762367684,80 -1078,1512762515954,86 -1079,1512762644069,86 -1080,1512762691167,85 -1081,1512762959954,85 -1082,1512763154591,83 -1083,1512763207819,81 -1084,1512763260405,82 -1085,1512763332360,81 -1086,1512763399798,79 -1087,1512763456758,79 -1088,1512763966539,80 -1089,1512764012917,76 -1090,1512764049943,77 -1091,1512764063203,79 -1092,1512764315819,89 -1093,1512764402885,87 -1094,1512764416857,85 -1095,1512764640420,103 -1096,1512764838811,100 -1097,1512764860436,99 -1098,1512764864703,105 -1099,1512765025158,161 -1100,1512765106744,158 -1101,1512765509616,157 -1102,1512766069493,153 -1103,1512766593736,150 -1104,1512766668769,146 -1105,1512766672896,146 -1106,1512766718702,229 -1107,1512767031286,235 -1108,1512767051794,231 -1109,1512767224258,252 -1110,1512767423046,252 -1111,1512767682014,248 -1112,1512767692742,250 -1113,1512768468580,299 -1114,1512769525696,294 -1115,1512770068202,287 -1116,1512771462276,281 -1117,1512772299557,275 -1118,1512772583109,269 -1119,1512775140605,264 -1120,1512777709527,257 -1121,1512778312557,250 -1122,1512779604479,246 -1123,1512780362352,239 -1124,1512781996106,234 -1125,1512782992140,226 -1126,1512783916134,220 -1127,1512784504823,214 -1128,1512785106927,208 -1129,1512785767619,202 -1130,1512786468803,197 -1131,1512786890051,192 -1132,1512787716744,186 -1133,1512789136789,182 -1134,1512789917484,177 -1135,1512790672413,171 -1136,1512791406292,165 -1137,1512792527677,159 -1138,1512793733998,152 -1139,1512794735158,146 -1140,1512795126528,143 -1141,1512795549325,136 -1142,1512795932700,130 -1143,1512796073774,126 -1144,1512796202009,120 -1145,1512796322918,117 -1146,1512797207441,113 -1147,1512797957799,107 -1148,1512798380977,102 -1149,1512798827974,96 -1150,1512799382954,89 -1151,1512799592692,86 -1152,1512799644047,81 -1153,1512799670976,84 -1154,1512799763778,84 -1155,1512799972150,81 -1156,1512800162622,75 -1157,1512801002937,70 -1158,1512801622141,63 -1159,1512801770918,57 -1160,1512801916035,55 -1161,1512802026524,50 -1162,1512802292776,45 -1163,1512802462458,40 -1164,1512802536984,37 -1165,1512802611518,32 -1166,1512802688297,27 -1167,1512802733283,23 -1168,1512802776376,25 -1169,1512802850064,22 -1170,1512802958904,17 -1171,1512803046980,11 -1172,1512803109022,5 -1173,1512803120955,1 -1174,1512803134680,1 -1175,1512803149522,1 -1176,1512803164587,1 -1177,1512803179600,1 -1178,1512803194524,1 -1179,1512803210999,1 -1180,1512803224090,1 -1181,1512803229793,1 -1182,1512803242750,1 -1183,1512803254642,1 -1184,1512803269570,1 -1185,1512803284699,1 -1186,1512803299510,1 -1187,1512803314713,1 -1188,1512803329499,1 -1189,1512803345862,1 -1190,1512803359730,1 -1191,1512803374535,1 -1192,1512803389744,1 -1193,1512803404819,1 -1194,1512803420072,1 -1195,1512803434535,1 -1196,1512803449679,1 -1197,1512803464793,1 -1198,1512803480936,1 -1199,1512803494525,1 -1200,1512803509576,1 -1201,1512803524715,1 -1202,1512803539819,1 -1203,1512803554847,1 -1204,1512803569758,1 -1205,1512803584711,1 -1206,1512803599659,1 -1207,1512803614752,1 -1208,1512803631213,1 -1209,1512803644621,1 -1210,1512803656050,1 -1211,1512803664355,1 -1212,1512803677917,1 -1213,1512803691826,3 -1214,1512803707719,3 -1215,1512803721116,3 -1216,1512803737770,3 -1217,1512803764829,3 -1218,1512803798583,3 -1219,1512803867075,3 -1220,1512803889685,3 -1221,1512803911174,2 -1222,1512803917451,1 -1223,1512803930986,2 -1224,1512803949832,2 -1225,1512803963312,1 -1226,1512803976827,1 -1227,1512803990957,1 -1228,1512804003514,1 -1229,1512804020948,1 -1230,1512804033548,1 -1231,1512804045310,1 -1232,1512804054662,1 -1233,1512804068871,1 -1234,1512804080292,1 -1235,1512804096566,1 -1236,1512804108645,1 -1237,1512804114937,1 -1238,1512804127412,1 -1239,1512804139281,1 -1240,1512804145006,1 -1241,1512804158514,1 -1242,1512804170092,1 -1243,1512804184963,1 -1244,1512804202694,1 -1245,1512804214811,1 -1246,1512804229609,1 -1247,1512804244660,1 -1248,1512804259689,1 -1249,1512804278364,1 -1250,1512804291761,1 -1251,1512804307251,1 -1252,1512804320506,1 -1253,1512804337529,1 -1254,1512804349772,1 -1255,1512804364790,1 -1256,1512804379602,1 -1257,1512804394844,1 -1258,1512804409685,2 -1259,1512804428746,1 -1260,1512804442555,2 -1261,1512804454885,2 -1262,1512804470417,2 -1263,1512804486957,3 -1264,1512804499611,3 -1265,1512804519876,3 -1266,1512804543690,4 -1267,1512804559863,4 -1268,1512804593392,5 -1269,1512804620023,6 -1270,1512804652533,7 -1271,1512804666168,7 -1272,1512804714434,8 -1273,1512804736620,8 -1274,1512804769314,9 -1275,1512804832586,9 -1276,1512804886693,9 -1277,1512804894805,10 -1278,1512804921608,12 -1279,1512804953609,12 -1280,1512804983377,13 -1281,1512805012308,14 -1282,1512805044501,15 -1283,1512805086946,16 -1284,1512805116652,16 -1285,1512805156590,17 -1286,1512805238580,17 -1287,1512805412893,17 -1288,1512805576558,18 -1289,1512805612322,17 -1290,1512805627828,17 -1291,1512805689049,20 -1292,1512805716086,21 -1293,1512805802873,22 -1294,1512805830909,22 -1295,1512805880089,23 -1296,1512805924988,24 -1297,1512805956547,24 -1298,1512805971699,26 -1299,1512806091570,29 -1300,1512806109423,29 -1301,1512806167237,32 -1302,1512806222164,33 -1303,1512806271626,33 -1304,1512806439749,34 -1305,1512806597255,34 -1306,1512806826361,33 -1307,1512807033593,33 -1308,1512807138648,33 -1309,1512807188967,33 -1310,1512807859108,33 -1311,1512808225229,32 -1312,1512808327620,32 -1313,1512808547765,32 -1314,1512808626755,31 -1315,1512808715558,31 -1316,1512808847007,31 -1317,1512809035043,31 -1318,1512809182805,31 -1319,1512809785346,31 -1320,1512810113631,30 -1321,1512810227512,29 -1322,1512810317403,29 -1323,1512810531330,29 -1324,1512810729863,29 -1325,1512810857588,28 -1326,1512810955245,28 -1327,1512811020475,28 -1328,1512811158464,27 -1329,1512811509161,28 -1330,1512811686414,26 -1331,1512811762916,26 -1332,1512811866413,26 -1333,1512812013472,26 -1334,1512812151717,25 -1335,1512812299308,24 -1336,1512812420616,24 -1337,1512812583608,24 -1338,1512812677379,23 -1339,1512812751827,23 -1340,1512812829153,22 -1341,1512812949301,22 -1342,1512813095154,22 -1343,1512813204358,21 -1344,1512813288826,21 -1345,1512813348567,21 -1346,1512813380450,20 -1347,1512813415093,20 -1348,1512813468996,21 -1349,1512813573566,21 -1350,1512813636278,20 -1351,1512813677147,20 -1352,1512813696937,20 -1353,1512813816477,21 -1354,1512813966762,20 -1355,1512814053532,18 -1356,1512814128506,19 -1357,1512814188577,18 -1358,1512814220782,18 -1359,1512814282217,18 -1360,1512814345045,18 -1361,1512814382598,18 -1362,1512814476173,17 -1363,1512814521106,17 -1364,1512814642877,17 -1365,1512814669996,16 -1366,1512814698889,16 -1367,1512814733724,17 -1368,1512814859791,16 -1369,1512814921611,16 -1370,1512815018431,16 -1371,1512815134290,15 -1372,1512815166669,14 -1373,1512815208278,14 -1374,1512815255207,14 -1375,1512815298799,14 -1376,1512815334968,13 -1377,1512815372310,14 -1378,1512815435122,14 -1379,1512815482855,14 -1380,1512815511691,15 -1381,1512815673458,14 -1382,1512815795703,14 -1383,1512815889883,14 -1384,1512815948924,14 -1385,1512816007988,14 -1386,1512816067043,14 -1387,1512816125694,13 -1388,1512816364379,13 -1389,1512816474263,12 -1390,1512816496400,11 -1391,1512816542918,12 -1392,1512816563677,12 -1393,1512816591195,13 -1394,1512816624883,13 -1395,1512816721907,15 -1396,1512816785090,14 -1397,1512816856651,14 -1398,1512816918220,15 -1399,1512816950522,16 -1400,1512817008251,16 -1401,1512817024953,18 -1402,1512817073535,20 -1403,1512817103310,21 -1404,1512817187425,22 -1405,1512817280050,21 -1406,1512817372183,22 -1407,1512817488032,22 -1408,1512817539219,21 -1409,1512817641396,21 -1410,1512817691316,21 -1411,1512817747103,21 -1412,1512817839492,21 -1413,1512818039801,21 -1414,1512818139671,21 -1415,1512818199894,20 -1416,1512818272999,21 -1417,1512818369814,20 -1418,1512818400572,20 -1419,1512818446876,21 -1420,1512818507482,21 -1421,1512818583021,21 -1422,1512818613910,20 -1423,1512818658000,21 -1424,1512818792936,22 -1425,1512818855037,21 -1426,1512818901567,21 -1427,1512818930179,21 -1428,1512819032476,23 -1429,1512819198041,22 -1430,1512819288248,22 -1431,1512819321636,21 -1432,1512819437490,22 -1433,1512819488029,21 -1434,1512819620007,22 -1435,1512819691404,21 -1436,1512819740732,21 -1437,1512819876862,20 -1438,1512819994941,19 -1439,1512820159433,19 -1440,1512820222761,19 -1441,1512820269495,19 -1442,1512820357629,19 -1443,1512820385127,19 -1444,1512820401806,19 -1445,1512820492165,20 -1446,1512820550304,19 -1447,1512820640299,21 -1448,1512820747774,21 -1449,1512820778298,20 -1450,1512820794842,21 -1451,1512820822408,23 -1452,1512820852534,25 -1453,1512820955518,27 -1454,1512821060123,27 -1455,1512821094957,26 -1456,1512821179794,27 -1457,1512821252484,26 -1458,1512821271308,27 -1459,1512821359365,29 -1460,1512821408889,29 -1461,1512821493182,29 -1462,1512821540210,30 -1463,1512821686973,30 -1464,1512821866164,29 -1465,1512821954846,29 -1466,1512822008081,29 -1467,1512822063474,29 -1468,1512822369742,30 -1469,1512822545265,29 -1470,1512822577211,29 -1471,1512822754572,29 -1472,1512822841483,28 -1473,1512822866544,28 -1474,1512822920485,30 -1475,1512822959317,30 -1476,1512823059537,32 -1477,1512823191502,31 -1478,1512823368399,31 -1479,1512823463687,30 -1480,1512823551785,30 -1481,1512823630213,30 -1482,1512823660090,30 -1483,1512823761632,30 -1484,1512823870203,30 -1485,1512823925326,30 -1486,1512823955184,30 -1487,1512824133323,31 -1488,1512824183320,30 -1489,1512824209078,31 -1490,1512824227530,32 -1491,1512824271846,35 -1492,1512824496849,36 -1493,1512824692259,35 -1494,1512824708111,35 -1495,1512824721689,39 -1496,1512824783557,44 -1497,1512824840212,44 -1498,1512824932556,45 -1499,1512825122492,44 -1500,1512825241626,44 -1501,1512825414229,44 -1502,1512825493584,43 -1503,1512825653223,43 -1504,1512825738252,43 -1505,1512825798467,43 -1506,1512825864354,43 -1507,1512825952326,43 -1508,1512826086928,43 -1509,1512826210350,42 -1510,1512826296382,41 -1511,1512826372427,41 -1512,1512826431908,41 -1513,1512826552718,41 -1514,1512826727025,41 -1515,1512826881477,39 -1516,1512826972465,39 -1517,1512827000547,38 -1518,1512827180738,40 -1519,1512827282142,39 -1520,1512827326145,40 -1521,1512827402567,39 -1522,1512827464779,39 -1523,1512827523537,40 -1524,1512827555835,40 -1525,1512827751391,41 -1526,1512827858322,41 -1527,1512827978085,40 -1528,1512828052127,39 -1529,1512828081884,39 -1530,1512828142599,41 -1531,1512828280250,40 -1532,1512828380136,40 -1533,1512828437028,40 -1534,1512828502125,40 -1535,1512828565301,39 -1536,1512828692602,40 -1537,1512828924804,38 -1538,1512829159449,36 -1539,1512829195157,35 -1540,1512829372325,36 -1541,1512829771890,35 -1542,1512829896563,32 -1543,1512829927197,32 -1544,1512830252431,32 -1545,1512830498086,32 -1546,1512830558935,31 -1547,1512830601595,31 -1548,1512830794735,32 -1549,1512830899624,29 -1550,1512830976821,29 -1551,1512831231534,30 -1552,1512831337765,29 -1553,1512831396835,29 -1554,1512831487620,28 -1555,1512831520419,27 -1556,1512831577302,29 -1557,1512831767437,28 -1558,1512831863808,27 -1559,1512831893143,28 -1560,1512831949254,28 -1561,1512832009070,28 -1562,1512832131956,28 -1563,1512832217296,27 -1564,1512832252756,26 -1565,1512832400886,26 -1566,1512832730554,26 -1567,1512832852540,24 -1568,1512832898589,23 -1569,1512832940587,23 -1570,1512832960320,22 -1571,1512833072711,23 -1572,1512833199729,22 -1573,1512833267586,22 -1574,1512833301778,21 -1575,1512833378574,22 -1576,1512833409504,21 -1577,1512833437355,22 -1578,1512833479833,22 -1579,1512833539323,22 -1580,1512833586704,21 -1581,1512833777553,21 -1582,1512833873832,19 -1583,1512833903168,19 -1584,1512833932258,19 -1585,1512833958109,19 -1586,1512833976738,20 -1587,1512834000921,21 -1588,1512834040069,22 -1589,1512834138841,22 -1590,1512834201756,22 -1591,1512834322045,23 -1592,1512834454502,23 -1593,1512834710623,21 -1594,1512834978021,19 -1595,1512835118712,21 -1596,1512835201207,23 -1597,1512835523716,22 -1598,1512835689524,23 -1599,1512835732363,21 -1600,1512835822070,22 -1601,1512835910589,21 -1602,1512835945377,20 -1603,1512836087216,20 -1604,1512836149702,19 -1605,1512836197726,20 -1606,1512836493310,20 -1607,1512836634804,19 -1608,1512836687650,18 -1609,1512836739395,18 -1610,1512836778693,17 -1611,1512836917006,18 -1612,1512837022167,17 -1613,1512837062445,17 -1614,1512837107519,17 -1615,1512837173926,16 -1616,1512837201901,15 -1617,1512837271756,15 -1618,1512837429822,16 -1619,1512837550429,15 -1620,1512837617708,15 -1621,1512837681829,15 -1622,1512837766697,14 -1623,1512837802620,14 -1624,1512837900160,15 -1625,1512837948991,15 -1626,1512837964137,15 -1627,1512838006759,16 -1628,1512838024094,16 -1629,1512838043887,18 -1630,1512838144359,20 -1631,1512838194756,20 -1632,1512838206690,19 -1633,1512838239800,23 -1634,1512838309324,23 -1635,1512838370362,23 -1636,1512838444363,24 -1637,1512838683467,23 -1638,1512838881693,22 -1639,1512838965752,22 -1640,1512838988750,22 -1641,1512839029458,22 -1642,1512839131809,24 -1643,1512839179268,23 -1644,1512839215105,23 -1645,1512839267427,23 -1646,1512839303655,23 -1647,1512839330145,24 -1648,1512839365112,26 -1649,1512839404289,27 -1650,1512839423618,27 -1651,1512839454546,29 -1652,1512839538867,30 -1653,1512839664916,30 -1654,1512839828169,29 -1655,1512839900278,29 -1656,1512839948580,29 -1657,1512839994508,29 -1658,1512840095040,30 -1659,1512840154231,29 -1660,1512840189010,30 -1661,1512840265276,31 -1662,1512840354190,31 -1663,1512840399400,31 -1664,1512840484426,31 -1665,1512840576782,31 -1666,1512840616903,31 -1667,1512840662442,31 -1668,1512840691288,31 -1669,1512840742512,33 -1670,1512840887527,34 -1671,1512840948955,33 -1672,1512841051304,34 -1673,1512841208594,34 -1674,1512841415451,33 -1675,1512841534936,32 -1676,1512841773076,32 -1677,1512841908827,31 -1678,1512841942174,31 -1679,1512841984519,33 -1680,1512842014662,33 -1681,1512842063398,35 -1682,1512842078596,35 -1683,1512842170442,39 -1684,1512842254648,39 -1685,1512842300400,39 -1686,1512842554845,41 -1687,1512842691905,40 -1688,1512842732817,41 -1689,1512842871348,42 -1690,1512842959685,42 -1691,1512843122981,42 -1692,1512843347939,40 -1693,1512843438654,39 -1694,1512843485529,38 -1695,1512843614838,39 -1696,1512843700135,38 -1697,1512843760271,38 -1698,1512843904857,38 -1699,1512844073384,37 -1700,1512844102551,36 -1701,1512844299693,38 -1702,1512844420934,37 -1703,1512844596482,37 -1704,1512844733728,36 -1705,1512844833012,35 -1706,1512844865083,34 -1707,1512844936315,35 -1708,1512845033516,35 -1709,1512845091667,34 -1710,1512845167574,34 -1711,1512845267645,34 -1712,1512845350184,33 -1713,1512845442585,32 -1714,1512845482072,32 -1715,1512845544449,32 -1716,1512845570684,32 -1717,1512845585034,34 -1718,1512845990085,38 -1719,1512846214473,36 -1720,1512846409511,35 -1721,1512846558366,33 -1722,1512846604503,31 -1723,1512846698503,32 -1724,1512846789565,32 -1725,1512846844144,31 -1726,1512846932412,31 -1727,1512846983185,30 -1728,1512847083257,31 -1729,1512847174485,31 -1730,1512847266931,30 -1731,1512847478748,30 -1732,1512847671960,28 -1733,1512847942450,29 -1734,1512848138660,28 -1735,1512848222330,27 -1736,1512848268408,26 -1737,1512848403497,26 -1738,1512848496021,24 -1739,1512848539352,24 -1740,1512848581764,24 -1741,1512848630520,24 -1742,1512848735885,24 -1743,1512848783390,23 -1744,1512848797185,23 -1745,1512848837646,26 -1746,1512848871706,26 -1747,1512848900315,26 -1748,1512848990892,28 -1749,1512849038011,28 -1750,1512849110191,28 -1751,1512849214789,29 -1752,1512849366582,28 -1753,1512849467809,28 -1754,1512849723337,27 -1755,1512849854453,25 -1756,1512849875859,25 -1757,1512849889606,27 -1758,1512849895203,30 -1759,1512850117620,42 -1760,1512850191982,41 -1761,1512850373213,41 -1762,1512850778191,40 -1763,1512850943185,39 -1764,1512850970811,37 -1765,1512851196516,39 -1766,1512851404719,38 -1767,1512851646083,37 -1768,1512851838458,37 -1769,1512851900779,36 -1770,1512852019908,37 -1771,1512852271391,35 -1772,1512852393616,35 -1773,1512852451970,34 -1774,1512852535383,34 -1775,1512852668809,32 -1776,1512852888086,32 -1777,1512852977483,30 -1778,1512853022815,29 -1779,1512853157138,31 -1780,1512853249006,29 -1781,1512853270278,29 -1782,1512853400574,31 -1783,1512853536477,33 -1784,1512853624084,33 -1785,1512853685961,32 -1786,1512853732762,33 -1787,1512853793819,32 -1788,1512853834579,32 -1789,1512854138117,34 -1790,1512854309937,32 -1791,1512854345648,32 -1792,1512854586937,33 -1793,1512854723357,30 -1794,1512854766586,31 -1795,1512854840632,30 -1796,1512854885728,30 -1797,1512855242403,30 -1798,1512855472237,30 -1799,1512855564914,28 -1800,1512855632479,27 -1801,1512855652155,28 -1802,1512855680377,30 -1803,1512855709125,30 -1804,1512855759203,31 -1805,1512855825939,31 -1806,1512855887276,31 -1807,1512855991912,31 -1808,1512856037089,31 -1809,1512856161931,31 -1810,1512856190985,31 -1811,1512856345391,31 -1812,1512856638711,31 -1813,1512856744013,30 -1814,1512856868566,29 -1815,1512857032424,29 -1816,1512857107751,28 -1817,1512857198199,29 -1818,1512857299651,31 -1819,1512857523011,28 -1820,1512857629531,28 -1821,1512857690137,27 -1822,1512857867886,26 -1823,1512857932933,26 -1824,1512858020167,25 -1825,1512858075269,25 -1826,1512858096822,25 -1827,1512858173724,26 -1828,1512858234582,26 -1829,1512858259577,26 -1830,1512858275337,27 -1831,1512858310124,30 -1832,1512858352375,30 -1833,1512858451747,30 -1834,1512858664834,29 -1835,1512858812524,28 -1836,1512858848915,27 -1837,1512859023857,27 -1838,1512859192288,26 -1839,1512859284484,24 -1840,1512859309988,24 -1841,1512859402206,25 -1842,1512859502529,24 -1843,1512859520610,23 -1844,1512859645171,25 -1845,1512859731331,25 -1846,1512860162302,25 -1847,1512860360031,24 -1848,1512860402896,24 -1849,1512860446678,24 -1850,1512860466891,24 -1851,1512860590118,25 -1852,1512860678860,24 -1853,1512860734709,23 -1854,1512860795218,23 -1855,1512860897128,22 -1856,1512860935421,21 -1857,1512860948636,21 -1858,1512861142851,26 -1859,1512861318184,31 -1860,1512861384596,30 -1861,1512861436042,30 -1862,1512861532161,30 -1863,1512861620506,29 -1864,1512861682339,29 -1865,1512861997061,30 -1866,1512862339834,28 -1867,1512862374399,26 -1868,1512862473495,27 -1869,1512862489786,27 -1870,1512862551933,30 -1871,1512862585000,30 -1872,1512862608256,30 -1873,1512862628541,32 -1874,1512862660394,35 -1875,1512862717486,36 -1876,1512862875165,36 -1877,1512862970853,35 -1878,1512863047916,34 -1879,1512863092953,35 -1880,1512863302810,35 -1881,1512863408331,33 -1882,1512863420002,34 -1883,1512863494354,40 -1884,1512863510961,39 -1885,1512863544265,43 -1886,1512863949741,45 -1887,1512864156805,44 -1888,1512864278431,43 -1889,1512864408054,43 -1890,1512864534807,42 -1891,1512864649833,41 -1892,1512864767750,42 -1893,1512864849267,40 -1894,1512864908145,40 -1895,1512864985871,40 -1896,1512865192413,40 -1897,1512865390685,40 -1898,1512865472148,38 -1899,1512865507708,38 -1900,1512865788853,39 -1901,1512866061824,37 -1902,1512866343416,37 -1903,1512866465749,37 -1904,1512866574702,37 -1905,1512866719693,36 -1906,1512866766200,36 -1907,1512866837881,36 -1908,1512866992048,36 -1909,1512867085619,36 -1910,1512867213579,35 -1911,1512867278035,34 -1912,1512867318857,35 -1913,1512867424149,35 -1914,1512867475148,34 -1915,1512867529841,34 -1916,1512867574726,34 -1917,1512867737959,34 -1918,1512867874790,33 -1919,1512868012537,31 -1920,1512868171678,31 -1921,1512868266723,30 -1922,1512868293360,29 -1923,1512868457853,30 -1924,1512868597458,29 -1925,1512868642811,27 -1926,1512868699799,28 -1927,1512868777175,28 -1928,1512868818367,27 -1929,1512868840745,28 -1930,1512868908885,30 -1931,1512868959496,30 -1932,1512869030647,32 -1933,1512869044799,32 -1934,1512869124526,36 -1935,1512869281660,36 -1936,1512869390045,34 -1937,1512869469804,34 -1938,1512869680756,32 -1939,1512869913946,31 -1940,1512870064762,30 -1941,1512870094725,30 -1942,1512870171835,31 -1943,1512870692894,30 -1944,1512870925303,29 -1945,1512870990954,28 -1946,1512871082932,27 -1947,1512871162824,26 -1948,1512871458000,25 -1949,1512871638980,25 -1950,1512871698916,24 -1951,1512871714876,24 -1952,1512871733794,26 -1953,1512871787201,28 -1954,1512871852677,28 -1955,1512872057069,27 -1956,1512872227428,26 -1957,1512872284759,25 -1958,1512872364601,26 -1959,1512872432879,25 -1960,1512872450667,24 -1961,1512872529999,26 -1962,1512872553983,26 -1963,1512872614675,27 -1964,1512872704359,26 -1965,1512872737226,25 -1966,1512872794358,25 -1967,1512872824915,24 -1968,1512873005136,25 -1969,1512873125269,23 -1970,1512873172160,24 -1971,1512873324148,24 -1972,1512873481749,23 -1973,1512873533862,23 -1974,1512873562397,24 -1975,1512873579487,26 -1976,1512873592054,28 -1977,1512873634786,32 -1978,1512873680820,32 -1979,1512873772183,32 -1980,1512874045351,32 -1981,1512874188996,31 -1982,1512874253786,30 -1983,1512874426303,33 -1984,1512874504998,32 -1985,1512874566037,34 -1986,1512874669040,35 -1987,1512874731974,34 -1988,1512874765700,34 -1989,1512874897438,35 -1990,1512875035217,35 -1991,1512875090943,34 -1992,1512875139415,34 -1993,1512875155454,34 -1994,1512875167666,38 -1995,1512875275886,44 -1996,1512875317914,44 -1997,1512875422378,45 -1998,1512875506317,44 -1999,1512875617257,44 -2000,1512875769014,44 -2001,1512876197938,43 -2002,1512876383263,41 -2003,1512876443552,41 -2004,1512876540912,40 -2005,1512876625024,40 -2006,1512876679858,39 -2007,1512876829480,40 -2008,1512876907673,39 -2009,1512877038073,38 -2010,1512877103932,38 -2011,1512877261767,37 -2012,1512877366816,36 -2013,1512877404906,37 -2014,1512877434905,37 -2015,1512877502265,39 -2016,1512877518541,39 -2017,1512877569073,44 -2018,1512877750537,44 -2019,1512878074941,43 -2020,1512878416819,41 -2021,1512878679363,39 -2022,1512878903095,38 -2023,1512878945376,38 -2024,1512878994344,39 -2025,1512879093034,38 -2026,1512879136815,38 -2027,1512879159796,39 -2028,1512879184491,41 -2029,1512879347220,43 -2030,1512879725256,43 -2031,1512880128158,42 -2032,1512880238384,41 -2033,1512880368094,40 -2034,1512880609971,41 -2035,1512880869581,41 -2036,1512880952305,39 -2037,1512881050774,38 -2038,1512881138021,38 -2039,1512881166017,37 -2040,1512881212734,38 -2041,1512881347306,39 -2042,1512881482287,38 -2043,1512881559605,37 -2044,1512881716513,37 -2045,1512881899921,34 -2046,1512881993202,34 -2047,1512882181915,33 -2048,1512882365211,32 -2049,1512882664723,30 -2050,1512882768580,29 -2051,1512882802213,28 -2052,1512882865215,29 -2053,1512882951021,30 -2054,1512882997895,29 -2055,1512883070786,29 -2056,1512883130053,29 -2057,1512883173489,27 -2058,1512883351918,27 -2059,1512883432330,26 -2060,1512883474968,26 -2061,1512883608781,27 -2062,1512883654958,26 -2063,1512883716248,26 -2064,1512883794295,25 -2065,1512883913700,25 -2066,1512884028054,24 -2067,1512884108312,23 -2068,1512884224494,23 -2069,1512884391124,21 -2070,1512884543805,20 -2071,1512884749545,19 -2072,1512884883632,17 -2073,1512884914881,16 -2074,1512884987299,16 -2075,1512885039781,15 -2076,1512885068347,15 -2077,1512885096794,18 -2078,1512885155022,18 -2079,1512885218340,18 -2080,1512885228747,17 -2081,1512885247164,19 -2082,1512885275051,21 -2083,1512885309961,21 -2084,1512885354941,21 -2085,1512885380994,21 -2086,1512885408533,22 -2087,1512885440072,22 -2088,1512885456321,23 -2089,1512885486400,25 -2090,1512885542366,25 -2091,1512885602328,25 -2092,1512885622439,25 -2093,1512885721827,26 -2094,1512885772120,27 -2095,1512885815747,30 -2096,1512885877358,30 -2097,1512885909852,31 -2098,1512885937788,33 -2099,1512886172290,34 -2100,1512886307136,33 -2101,1512886414517,33 -2102,1512886463008,30 -2103,1512887161886,30 -2104,1512887540007,30 -2105,1512887589029,29 -2106,1512887630991,29 -2107,1512887918569,30 -2108,1512888082883,28 -2109,1512888156031,27 -2110,1512888203019,27 -2111,1512888317355,27 -2112,1512888476049,27 -2113,1512888565242,25 -2114,1512888640783,26 -2115,1512888782418,26 -2116,1512888879395,25 -2117,1512888965497,27 -2118,1512889001437,27 -2119,1512889075511,26 -2120,1512889219845,27 -2121,1512889378123,25 -2122,1512889480319,25 -2123,1512889534704,23 -2124,1512889687307,25 -2125,1512889774642,23 -2126,1512889824506,23 -2127,1512889925248,24 -2128,1512889970396,25 -2129,1512890014678,26 -2130,1512890067702,26 -2131,1512890104635,26 -2132,1512890123693,26 -2133,1512890163876,29 -2134,1512890186426,30 -2135,1512890243400,31 -2136,1512890284299,31 -2137,1512890342731,31 -2138,1512890405407,32 -2139,1512890471727,32 -2140,1512890652595,32 -2141,1512890826863,33 -2142,1512890936571,32 -2143,1512891049654,31 -2144,1512891138209,30 -2145,1512891207545,30 -2146,1512891249293,30 -2147,1512891319234,30 -2148,1512891355691,30 -2149,1512891370640,30 -2150,1512891484212,33 -2151,1512891744260,33 -2152,1512891863510,32 -2153,1512892055468,31 -2154,1512892163305,30 -2155,1512892285588,31 -2156,1512892466711,30 -2157,1512892641976,28 -2158,1512892854442,27 -2159,1512893062858,27 -2160,1512893153724,26 -2161,1512893184822,26 -2162,1512893239299,27 -2163,1512893396099,26 -2164,1512893472640,26 -2165,1512893572619,25 -2166,1512893794223,24 -2167,1512894005438,23 -2168,1512894123477,22 -2169,1512894178259,22 -2170,1512894274632,20 -2171,1512894334620,20 -2172,1512894381909,18 -2173,1512894469331,18 -2174,1512894591915,17 -2175,1512894653686,16 -2176,1512894695045,16 -2177,1512894981853,16 -2178,1512895160415,15 -2179,1512895252360,14 -2180,1512895299290,13 -2181,1512895359268,14 -2182,1512895404489,14 -2183,1512895450358,14 -2184,1512895479625,14 -2185,1512895505454,14 -2186,1512895585728,15 -2187,1512895629311,15 -2188,1512895643397,15 -2189,1512895704955,18 -2190,1512895744563,18 -2191,1512895894598,18 -2192,1512896019248,17 -2193,1512896106867,18 -2194,1512896142836,18 -2195,1512896225845,18 -2196,1512896245359,18 -2197,1512896276756,20 -2198,1512896317882,20 -2199,1512896424451,22 -2200,1512896510378,21 -2201,1512896574383,21 -2202,1512896723164,20 -2203,1512896809587,20 -2204,1512896900316,19 -2205,1512897037835,18 -2206,1512897235300,18 -2207,1512897319619,17 -2208,1512897343198,17 -2209,1512897380030,18 -2210,1512897399676,17 -2211,1512897455259,20 -2212,1512897515366,19 -2213,1512897546195,18 -2214,1512897563417,19 -2215,1512897667758,21 -2216,1512897717489,20 -2217,1512897740301,20 -2218,1512897799565,20 -2219,1512897833306,21 -2220,1512897905259,22 -2221,1512898163085,21 -2222,1512898310210,20 -2223,1512898357573,19 -2224,1512898417092,19 -2225,1512898523440,18 -2226,1512898601925,18 -2227,1512898673538,18 -2228,1512898781554,17 -2229,1512898850253,16 -2230,1512898885790,16 -2231,1512898909931,17 -2232,1512898928371,18 -2233,1512899022453,20 -2234,1512899112623,20 -2235,1512899254071,21 -2236,1512899391811,21 -2237,1512899479509,21 -2238,1512899585252,21 -2239,1512899649204,21 -2240,1512899689104,20 -2241,1512899720648,21 -2242,1512899825307,21 -2243,1512899914141,20 -2244,1512899988449,20 -2245,1512900027206,20 -2246,1512900080635,21 -2247,1512900245302,20 -2248,1512900326594,21 -2249,1512900425264,21 -2250,1512900484416,23 -2251,1512900624277,23 -2252,1512900769493,22 -2253,1512901039937,21 -2254,1512901235744,21 -2255,1512901295936,20 -2256,1512901356444,20 -2257,1512901429809,20 -2258,1512901580579,18 -2259,1512901732277,19 -2260,1512901796235,18 -2261,1512901835884,18 -2262,1512901910981,19 -2263,1512901944817,19 -2264,1512901985943,20 -2265,1512902092285,19 -2266,1512902230222,19 -2267,1512902270660,18 -2268,1512902315063,19 -2269,1512902350010,18 -2270,1512902421943,19 -2271,1512902468890,19 -2272,1512902510143,19 -2273,1512902558586,19 -2274,1512902600452,19 -2275,1512902663191,19 -2276,1512902695443,19 -2277,1512902798213,20 -2278,1512902840804,19 -2279,1512902859836,18 -2280,1512902916374,20 -2281,1512902973109,20 -2282,1512903066299,20 -2283,1512903147110,19 -2284,1512903189690,19 -2285,1512903263769,19 -2286,1512903350828,19 -2287,1512903384003,18 -2288,1512903444112,19 -2289,1512903507064,20 -2290,1512903639522,20 -2291,1512903718409,20 -2292,1512903758839,19 -2293,1512903874553,19 -2294,1512903925185,18 -2295,1512903968263,18 -2296,1512904084635,19 -2297,1512904188420,18 -2298,1512904392769,19 -2299,1512904506525,18 -2300,1512904610698,18 -2301,1512904648238,17 -2302,1512904673790,17 -2303,1512904834005,18 -2304,1512904925816,17 -2305,1512904985824,16 -2306,1512905034759,16 -2307,1512905075688,16 -2308,1512905269912,16 -2309,1512905408209,15 -2310,1512905494871,16 -2311,1512905562242,16 -2312,1512905590851,16 -2313,1512905667403,16 -2314,1512905724772,16 -2315,1512905765111,17 -2316,1512905824433,17 -2317,1512906079179,17 -2318,1512906216348,17 -2319,1512906291039,16 -2320,1512906424449,17 -2321,1512906489326,17 -2322,1512906529649,16 -2323,1512906594528,16 -2324,1512906711008,16 -2325,1512906786917,16 -2326,1512906912987,16 -2327,1512907151988,15 -2328,1512907240561,15 -2329,1512907312879,14 -2330,1512907376520,13 -2331,1512907450488,13 -2332,1512907520946,13 -2333,1512907565619,14 -2334,1512907612067,14 -2335,1512907658801,14 -2336,1512907701202,14 -2337,1512907746914,14 -2338,1512907794460,14 -2339,1512907854189,13 -2340,1512907895458,13 -2341,1512907927115,14 -2342,1512907969886,15 -2343,1512908016732,15 -2344,1512908053198,14 -2345,1512908072559,14 -2346,1512908181707,16 -2347,1512908255180,16 -2348,1512908300652,15 -2349,1512908376798,16 -2350,1512908458151,16 -2351,1512908499436,16 -2352,1512908539468,16 -2353,1512908634111,15 -2354,1512908692844,15 -2355,1512908751794,15 -2356,1512908782647,14 -2357,1512908813622,14 -2358,1512908833300,15 -2359,1512908886806,16 -2360,1512908945258,15 -2361,1512908974448,15 -2362,1512909080238,16 -2363,1512909142051,16 -2364,1512909334050,16 -2365,1512909440293,15 -2366,1512909534180,15 -2367,1512909656737,14 -2368,1512909755299,14 -2369,1512909816020,14 -2370,1512909927866,15 -2371,1512909969178,14 -2372,1512909983191,14 -2373,1512910115159,16 -2374,1512910189046,15 -2375,1512910226256,15 -2376,1512910241335,16 -2377,1512910309523,18 -2378,1512910342275,18 -2379,1512910430534,18 -2380,1512910519914,20 -2381,1512910570234,19 -2382,1512910790271,20 -2383,1512910871412,19 -2384,1512911010407,19 -2385,1512911168621,19 -2386,1512911271027,18 -2387,1512911360786,18 -2388,1512911436184,18 -2389,1512911486465,18 -2390,1512911531774,18 -2391,1512911591879,19 -2392,1512911750459,18 -2393,1512911843409,18 -2394,1512911871082,18 -2395,1512911900502,19 -2396,1512912008452,20 -2397,1512912086160,19 -2398,1512912125303,19 -2399,1512912176430,19 -2400,1512912233037,19 -2401,1512912428516,19 -2402,1512912519259,20 -2403,1512912742650,20 -2404,1512912923222,19 -2405,1512912970989,19 -2406,1512913072238,19 -2407,1512913236047,18 -2408,1512913315861,18 -2409,1512913373099,18 -2410,1512913431489,18 -2411,1512913493493,18 -2412,1512913585258,18 -2413,1512913631207,18 -2414,1512913685154,18 -2415,1512913746709,18 -2416,1512913778935,18 -2417,1512913824499,19 -2418,1512913911026,19 -2419,1512913962092,19 -2420,1512914003370,19 -2421,1512914165310,18 -2422,1512914243301,18 -2423,1512914301776,19 -2424,1512914510228,18 -2425,1512914633391,17 -2426,1512914683075,16 -2427,1512914722125,17 -2428,1512915006776,17 -2429,1512915158073,16 -2430,1512915175879,16 -2431,1512915189187,18 -2432,1512915244462,20 -2433,1512915282928,20 -2434,1512915310366,20 -2435,1512915502700,21 -2436,1512915608131,20 -2437,1512915724538,20 -2438,1512915935061,20 -2439,1512916133086,19 -2440,1512916282472,17 -2441,1512916370264,18 -2442,1512916413985,18 -2443,1512916446988,18 -2444,1512916463157,18 -2445,1512916584473,21 -2446,1512916744593,21 -2447,1512916910207,20 -2448,1512917016877,20 -2449,1512917135229,19 -2450,1512917224554,19 -2451,1512917300251,18 -2452,1512917527440,18 -2453,1512917644578,18 -2454,1512917780189,17 -2455,1512917869124,17 -2456,1512917975217,17 -2457,1512918072254,16 -2458,1512918113092,16 -2459,1512918170204,17 -2460,1512918193153,17 -2461,1512918234551,18 -2462,1512918261942,19 -2463,1512918294499,20 -2464,1512918436789,20 -2465,1512918518890,19 -2466,1512918547357,19 -2467,1512918589472,19 -2468,1512918626892,20 -2469,1512918670990,20 -2470,1512918748242,21 -2471,1512918818778,20 -2472,1512918920146,20 -2473,1512918966003,20 -2474,1512919002838,21 -2475,1512919072300,21 -2476,1512919106941,21 -2477,1512919132997,23 -2478,1512919183176,23 -2479,1512919251213,25 -2480,1512919295111,24 -2481,1512919384695,25 -2482,1512919476544,24 -2483,1512919549729,24 -2484,1512919730878,24 -2485,1512919852264,24 -2486,1512919987297,23 -2487,1512920064276,22 -2488,1512920119659,22 -2489,1512920199450,22 -2490,1512920270118,22 -2491,1512920315186,22 -2492,1512920529585,22 -2493,1512920765656,22 -2494,1512920934067,21 -2495,1512921053566,20 -2496,1512921109453,20 -2497,1512921128405,21 -2498,1512921261744,22 -2499,1512921326221,22 -2500,1512921439752,22 -2501,1512921657736,22 -2502,1512921770254,21 -2503,1512921817422,21 -2504,1512921889087,20 -2505,1512921949495,20 -2506,1512921980713,21 -2507,1512922039075,20 -2508,1512922144436,21 -2509,1512922209226,19 -2510,1512922580189,19 -2511,1512922790955,19 -2512,1512922855721,19 -2513,1512922896009,19 -2514,1512922915696,18 -2515,1512923037060,19 -2516,1512923105224,20 -2517,1512923125847,19 -2518,1512923165980,21 -2519,1512923240275,22 -2520,1512923330999,22 -2521,1512923424418,22 -2522,1512923530017,21 -2523,1512923653247,20 -2524,1512923841188,20 -2525,1512923950829,19 -2526,1512924065174,19 -2527,1512924290536,18 -2528,1512924416262,18 -2529,1512924493038,16 -2530,1512924536020,16 -2531,1512924573837,16 -2532,1512924594934,18 -2533,1512924634141,18 -2534,1512924714599,20 -2535,1512924829579,20 -2536,1512924969716,20 -2537,1512925059722,18 -2538,1512925103189,18 -2539,1512925145119,18 -2540,1512925266746,18 -2541,1512925338974,18 -2542,1512925415235,17 -2543,1512925474528,18 -2544,1512925572664,17 -2545,1512925662233,18 -2546,1512925699929,17 -2547,1512925765295,18 -2548,1512925821333,18 -2549,1512925887546,17 -2550,1512925947273,17 -2551,1512926001269,17 -2552,1512926044851,16 -2553,1512926062110,16 -2554,1512926142151,17 -2555,1512926185653,17 -2556,1512926270126,17 -2557,1512926408723,16 -2558,1512926569684,16 -2559,1512926724766,15 -2560,1512926798945,15 -2561,1512926839703,15 -2562,1512926945851,15 -2563,1512927010858,15 -2564,1512927038983,15 -2565,1512927140104,15 -2566,1512927215920,14 -2567,1512927249601,15 -2568,1512927305494,15 -2569,1512927341181,15 -2570,1512927430997,16 -2571,1512927478246,16 -2572,1512927530987,16 -2573,1512927643218,16 -2574,1512927695884,15 -2575,1512927729643,16 -2576,1512927833190,16 -2577,1512927903884,15 -2578,1512927980357,16 -2579,1512928028395,17 -2580,1512928063132,16 -2581,1512928113674,17 -2582,1512928151452,17 -2583,1512928178503,17 -2584,1512928250420,19 -2585,1512928301486,17 -2586,1512928399908,18 -2587,1512928460878,18 -2588,1512928486918,17 -2589,1512928506993,17 -2590,1512928583390,19 -2591,1512928628477,19 -2592,1512928703038,20 -2593,1512928766551,19 -2594,1512928869726,19 -2595,1512928930677,18 -2596,1512928955728,18 -2597,1512928972969,20 -2598,1512929124394,22 -2599,1512929254648,22 -2600,1512929344354,22 -2601,1512929394558,21 -2602,1512929574514,21 -2603,1512929680391,21 -2604,1512929797332,20 -2605,1512929916422,20 -2606,1512930034057,20 -2607,1512930245180,19 -2608,1512930339931,19 -2609,1512930535382,19 -2610,1512930717877,18 -2611,1512930829886,18 -2612,1512930904466,17 -2613,1512931086199,16 -2614,1512931177129,17 -2615,1512931270803,16 -2616,1512931387257,16 -2617,1512931461069,16 -2618,1512931505720,16 -2619,1512931564945,16 -2620,1512931684849,17 -2621,1512931744779,17 -2622,1512931762175,16 -2623,1512931789597,17 -2624,1512931895009,18 -2625,1512931984994,17 -2626,1512932018623,17 -2627,1512932062135,18 -2628,1512932141322,18 -2629,1512932242454,17 -2630,1512932329913,17 -2631,1512932375170,17 -2632,1512932403639,17 -2633,1512932464786,18 -2634,1512932524485,18 -2635,1512932572333,18 -2636,1512932644887,19 -2637,1512932679355,18 -2638,1512932862689,19 -2639,1512932975229,18 -2640,1512933103269,17 -2641,1512933174490,17 -2642,1512933189019,17 -2643,1512933216549,19 -2644,1512933320098,20 -2645,1512933380159,20 -2646,1512933519801,19 -2647,1512933589293,19 -2648,1512933622469,19 -2649,1512933667494,19 -2650,1512933804757,20 -2651,1512933904788,20 -2652,1512933934746,19 -2653,1512934055943,20 -2654,1512934223399,20 -2655,1512934295588,20 -2656,1512934416754,20 -2657,1512934494130,19 -2658,1512934535655,19 -2659,1512934685196,19 -2660,1512934790273,18 -2661,1512934897707,18 -2662,1512935028434,18 -2663,1512935122440,17 -2664,1512935195296,16 -2665,1512935283748,16 -2666,1512935343637,16 -2667,1512935449512,16 -2668,1512935510886,16 -2669,1512935630839,15 -2670,1512935753498,16 -2671,1512935799805,14 -2672,1512935826265,15 -2673,1512935863107,15 -2674,1512935937117,15 -2675,1512936006341,15 -2676,1512936034856,15 -2677,1512936073447,15 -2678,1512936148321,15 -2679,1512936260653,15 -2680,1512936395173,15 -2681,1512936476436,14 -2682,1512936502772,15 -2683,1512936529447,15 -2684,1512936589581,16 -2685,1512936649872,16 -2686,1512936671774,16 -2687,1512936725494,17 -2688,1512936892820,17 -2689,1512937010159,16 -2690,1512937048481,17 -2691,1512937120622,18 -2692,1512937180231,16 -2693,1512937235029,16 -2694,1512937270885,16 -2695,1512937309736,16 -2696,1512937386111,16 -2697,1512937430667,18 -2698,1512937450656,19 -2699,1512937490618,21 -2700,1512937535538,21 -2701,1512937599336,22 -2702,1512937663009,22 -2703,1512937721417,21 -2704,1512937941684,22 -2705,1512938139460,21 -2706,1512938225671,20 -2707,1512938284147,20 -2708,1512938319758,20 -2709,1512938509859,20 -2710,1512938645136,20 -2711,1512938697032,19 -2712,1512938751154,19 -2713,1512938842262,19 -2714,1512938976287,18 -2715,1512939040427,18 -2716,1512939064387,18 -2717,1512939139273,19 -2718,1512939216245,18 -2719,1512939288993,18 -2720,1512939339448,18 -2721,1512939386912,18 -2722,1512939472023,18 -2723,1512986278727,18 -2724,1512986330560,18 -2725,1512986353260,18 -2726,1512986546838,18 -2727,1512986720358,17 -2728,1512986744761,17 -2729,1512986834498,19 -2730,1512986999853,17 -2731,1512987020432,18 -2732,1512987072224,19 -2733,1512987143731,20 -2734,1512987267567,19 -2735,1512987379728,19 -2736,1512987404798,19 -2737,1512987466896,20 -2738,1512987582215,21 -2739,1512987838734,19 -2740,1512987854672,19 -2741,1512987860296,21 -2742,1512987945128,29 -2743,1512988247973,30 -2744,1512988502631,29 -2745,1512988874210,29 -2746,1513169019670,28 -2747,1513169037556,27 -2748,1513169222313,30 -2749,1513169341163,30 -2750,1513169355800,29 -2751,1513169380083,33 -2752,1513169391201,35 -2753,1513169406304,42 -2754,1513169561395,48 -2755,1513169662291,47 -2756,1513169714826,46 -2757,1513169728497,48 -2758,1513169838753,55 -2759,1513170021569,55 -2760,1513170130348,54 -2761,1513170159538,53 -2762,1513170194193,56 -2763,1513170320272,59 -2764,1513170436942,59 -2765,1513170491060,58 -2766,1513170555205,58 -2767,1513170699016,59 -2768,1513170706164,59 -2769,1513170841624,76 -2770,1513171149892,76 -2771,1513171517920,75 -2772,1513171951719,73 -2773,1513172051598,72 -2774,1513172162875,73 -2775,1513172348918,71 -2776,1513172605196,71 -2777,1513172701712,70 -2778,1513172727286,70 -2779,1513172804360,74 -2780,1513172958380,75 -2781,1513173086881,73 -2782,1513173124708,73 -2783,1513173189674,75 -2784,1513173203486,76 -2785,1513173229838,88 -2786,1513173276987,93 -2787,1513173677474,95 -2788,1513174142060,94 -2789,1513174155810,92 -2790,1513174356609,105 -2791,1513174844033,104 -2792,1513175021343,102 -2793,1513175612640,100 -2794,1513175765055,98 -2795,1513175857081,97 -2796,1513175907276,96 -2797,1513175926726,98 -2798,1513176022704,109 -2799,1513176357626,109 -2800,1513176626886,107 -2801,1513176741290,105 -2802,1513176931614,104 -2803,1513177501279,103 -2804,1513177514861,101 -2805,1513177885940,115 -2806,1513178266990,112 -2807,1513178346182,109 -2808,1513178708054,109 -2809,1513178715307,108 -2810,1513179135258,139 -2811,1513179226243,136 -2812,1513179411859,136 -2813,1513179434049,134 -2814,1513179554802,144 -2815,1513179785412,143 -2816,1513180140008,141 -2817,1513180308234,137 -2818,1513180608799,135 -2819,1513180666858,132 -2820,1513180877621,134 -2821,1513181061140,130 -2822,1513181370044,128 -2823,1513181423412,124 -2824,1513181949519,125 -2825,1513182356016,122 -2826,1513182484809,119 -2827,1513182591089,116 -2828,1513182608049,115 -2829,1513182994489,127 -2830,1513183030260,123 -2831,1513183077619,126 -2832,1513183175909,129 -2833,1513183385167,127 -2834,1513183417532,124 -2835,1513183424624,127 -2836,1513183444875,166 -2837,1513183546843,180 -2838,1513183712527,179 -2839,1513184066399,175 -2840,1513184175878,170 -2841,1513184529560,169 -2842,1513185044227,168 -2843,1513185359299,163 -2844,1513185450389,158 -2845,1513185509517,157 -2846,1513185627154,156 -2847,1513185631297,153 -2848,1513185706252,237 -2849,1513185776510,237 -2850,1513185853775,238 -2851,1513185913612,239 -2852,1513185958068,242 -2853,1513186071621,252 -2854,1513186705595,252 -2855,1513187152572,245 -2856,1513187733614,239 -2857,1513188715264,233 -2858,1513188850069,229 -2859,1513189884984,225 -2860,1513190464889,218 -2861,1513190514483,212 -2862,1513190724771,217 -2863,1513190840960,213 -2864,1513191730926,210 -2865,1513192327619,202 -2866,1513192464495,196 -2867,1513192641944,192 -2868,1513192778903,188 -2869,1513193061276,193 -2870,1513193240961,187 -2871,1513193383206,182 -2872,1513193402361,177 -2873,1513193483412,191 -2874,1513193835624,190 -2875,1513193842976,184 -2876,1513193931534,236 -2877,1513194140874,233 -2878,1513194338266,227 -2879,1513194456481,224 -2880,1513194685974,220 -2881,1513194950855,214 -2882,1513194979566,207 -2883,1513196199747,217 -2884,1513196768891,209 -2885,1513197293496,207 -2886,1513197324944,203 -2887,1513197504356,211 -2888,1513197526612,205 -2889,1513197645359,218 -2890,1513198294292,221 -2891,1513198538201,213 -2892,1513198767228,206 -2893,1513199004783,199 -2894,1513199707418,191 -2895,1513200296425,183 -2896,1513200524734,175 -2897,1513200595924,170 -2898,1513201002750,172 -2899,1513201259844,165 -2900,1513201797497,157 -2901,1513202553317,149 -2902,1513202714065,141 -2903,1513202813930,135 -2904,1513203572358,128 -2905,1513204590553,128 -2906,1513204607060,120 -2907,1513204669243,128 -2908,1513204838242,126 -2909,1513205198327,119 -2910,1513205209301,129 -2911,1513205467111,148 -2912,1513205541529,142 -2913,1513205671007,138 -2914,1513205744676,139 -2915,1513205824161,135 -2916,1513205828127,131 -2917,1513206077636,201 -2918,1513206598974,193 -2919,1513207191885,184 -2920,1513207786258,177 -2921,1513207890326,169 -2922,1513207958500,163 -2923,1513208293834,158 -2924,1513208766726,152 -2925,1513209633500,142 -2926,1513209733392,133 -2927,1513209832576,127 -2928,1513209860647,120 -2929,1513210305365,128 -2930,1513210530085,120 -2931,1513210788364,114 -2932,1513211160348,109 -2933,1513211189774,100 -2934,1513211340810,99 -2935,1513211389001,95 -2936,1513211409415,112 -2937,1513211519995,126 -2938,1513211527197,121 -2939,1513211576339,153 -2940,1513211744446,151 -2941,1513212135734,146 -2942,1513212363017,136 -2943,1513212553762,129 -2944,1513212746414,120 -2945,1513213010226,114 -2946,1513213232997,109 -2947,1513213310696,102 -2948,1513213462449,140 -2949,1513213757741,138 -2950,1513213957950,135 -2951,1513215104893,131 -2952,1513215165488,128 -2953,1513215489219,131 -2954,1513215648218,127 -2955,1513215793289,121 -2956,1513216418743,116 -2957,1513216497705,108 -2958,1513216738527,104 -2959,1513216822694,99 -2960,1513216839243,95 -2961,1513216921147,100 -2962,1513217117038,101 -2963,1513217522972,95 -2964,1513217958034,89 -2965,1513217994849,82 -2966,1513218061805,80 -2967,1513218148286,76 -2968,1513218247046,71 -2969,1513218316619,66 -2970,1513218433058,62 -2971,1513218638497,56 -2972,1513218843340,50 -2973,1513218928799,54 -2974,1513219001542,51 -2975,1513219079938,45 -2976,1513219144657,69 -2977,1513219220130,69 -2978,1513219367047,66 -2979,1513219387243,61 -2980,1513219412435,64 -2981,1513219447120,65 -2982,1513219508513,63 -2983,1513219567315,68 -2984,1513219743538,64 -2985,1513219797782,59 -2986,1513219853869,56 -2987,1513219999275,59 -2988,1513220013012,55 -2989,1513220082123,69 -2990,1513220184900,67 -2991,1513220378367,64 -2992,1513220407248,59 -2993,1513220522638,58 -2994,1513220682631,55 -2995,1513220705454,50 -2996,1513220865366,49 -2997,1513220924777,44 -2998,1513220947577,43 -2999,1513220967540,41 -3000,1513221092941,40 -3001,1513221252704,36 -3002,1513221269195,30 -3003,1513221276295,28 -3004,1513221393404,34 -3005,1513221400892,28 -3006,1513221434376,30 -3007,1513221468904,35 -3008,1513221656525,33 -3009,1513221724312,28 -3010,1513221877810,24 -3011,1513221998363,32 -3012,1513222022319,27 -3013,1513222094877,27 -3014,1513222166066,23 -3015,1513222191170,20 -3016,1513222223139,19 -3017,1513222268881,55 -3018,1513222291216,54 -3019,1513222317074,56 -3020,1513222381804,57 -3021,1513222407743,54 -3022,1513222457877,57 -3023,1513222505016,57 -3024,1513222534362,56 -3025,1513222622379,56 -3026,1513222721197,53 -3027,1513222740699,51 -3028,1513222930793,54 -3029,1513222956351,56 -3030,1513223003678,57 -3031,1513223236234,55 -3032,1513223265320,51 -3033,1513223304100,51 -3034,1513223364677,54 -3035,1513223426113,52 -3036,1513223650812,51 -3037,1513223937272,54 -3038,1513224193763,51 -3039,1513224230663,67 -3040,1513224378021,72 -3041,1513224424556,70 -3042,1513224448347,71 -3043,1513224475832,75 -3044,1513224544782,78 -3045,1513224688991,77 -3046,1513224782498,75 -3047,1513224811672,74 -3048,1513225098504,77 -3049,1513225105804,75 -3050,1513225241540,96 -3051,1513225359015,94 -3052,1513225372169,92 -3053,1513225652826,107 -3054,1513226018678,103 -3055,1513226181252,100 -3056,1513226223057,98 -3057,1513226324253,99 -3058,1513226466053,98 -3059,1513226610253,96 -3060,1513226802697,94 -3061,1513227079998,98 -3062,1513227171114,95 -3063,1513227208888,94 -3064,1513227237592,96 -3065,1513227352607,99 -3066,1513227496633,99 -3067,1513227665306,98 -3068,1513227825997,95 -3069,1513227830087,94 -3070,1513228182152,145 -3071,1513228340790,141 -3072,1513228507870,139 -3073,1513228982582,135 -3074,1513228986416,132 -3075,1513229194948,209 -3076,1513229770788,206 -3077,1513229800708,201 -3078,1513229877268,212 -3079,1513229999551,212 -3080,1513230322676,213 -3081,1513230638332,211 -3082,1513231124367,208 -3083,1513231214803,203 -3084,1513231614940,204 -3085,1513232095539,198 -3086,1513232403289,193 -3087,1513232654011,190 -3088,1513232906061,186 -3089,1513232947126,185 -3090,1513233230527,190 -3091,1513233434074,186 -3092,1513233659707,182 -3093,1513233853675,180 -3094,1513234051345,176 -3095,1513234645447,171 -3096,1513235193437,167 -3097,1513235307459,162 -3098,1513235571128,159 -3099,1513235827880,157 -3100,1513235899104,154 -3101,1513235988229,153 -3102,1513236159577,150 -3103,1513236276839,148 -3104,1513236402310,150 -3105,1513236611658,146 -3106,1513237002852,146 -3107,1513237349687,140 -3108,1513237544895,136 -3109,1513237652709,131 -3110,1513238552017,129 -3111,1513238699488,123 -3112,1513238900837,118 -3113,1513238968178,115 -3114,1513239280261,112 -3115,1513239343432,107 -3116,1513239435487,105 -3117,1513239574980,102 -3118,1513239868637,99 -3119,1513239872645,96 -3120,1513239876692,149 -3121,1513240292698,232 -3122,1513240561658,227 -3123,1513240578022,221 -3124,1513240944377,247 -3125,1513241467668,242 -3126,1513241484725,234 -3127,1513241550711,259 -3128,1513242010652,262 -3129,1513242118095,254 -3130,1513242361811,253 -3131,1513242536456,247 -3132,1513243123621,241 -3133,1513243382686,235 -3134,1513243949962,229 -3135,1513244758167,222 -3136,1513244952972,214 -3137,1513245299594,207 -3138,1513246152472,199 -3139,1513246252408,190 -3140,1513246533436,188 -3141,1513247259481,180 -3142,1513247589338,173 -3143,1513247630230,168 -3144,1513247763008,172 -3145,1513248335550,167 -3146,1513249272982,159 -3147,1513249366418,152 -3148,1513249683904,148 -3149,1513249835981,141 -3150,1513250295595,146 -3151,1513250785590,139 -3152,1513251234278,131 -3153,1513251373205,132 -3154,1513251686979,126 -3155,1513251866431,118 -3156,1513251955366,112 -3157,1513252056670,109 -3158,1513252606269,103 -3159,1513252613468,96 -3160,1513252771443,120 -3161,1513252902096,114 -3162,1513253124598,107 -3163,1513253191660,99 -3164,1513253264604,97 -3165,1513253363523,96 -3166,1513254221190,89 -3167,1513254238594,82 -3168,1513254372096,85 -3169,1513254523716,78 -3170,1513254584354,97 -3171,1513254682187,94 -3172,1513254890207,89 -3173,1513254956923,82 -3174,1513254993610,76 -3175,1513255083585,115 -3176,1513255267222,112 -3177,1513255540502,107 -3178,1513256531364,109 -3179,1513256797071,105 -3180,1513256823080,101 -3181,1513257134548,105 -3182,1513257189487,99 -3183,1513257302626,96 -3184,1513257429485,94 -3185,1513257849993,90 -3186,1513258014325,84 -3187,1513258104601,78 -3188,1513258210381,74 -3189,1513258267141,69 -3190,1513258292096,71 -3191,1513258440556,72 -3192,1513258476392,68 -3193,1513258534283,65 -3194,1513258538779,62 -3195,1513258746193,90 -3196,1513259009840,83 -3197,1513259364528,77 -3198,1513259574135,72 -3199,1513259606682,66 -3200,1513259633471,64 -3201,1513259647280,64 -3202,1513259705231,70 -3203,1513259892616,67 -3204,1513259946970,61 -3205,1513260002627,57 -3206,1513260275519,53 -3207,1513260286549,46 -3208,1513260314498,49 -3209,1513260468403,47 -3210,1513260531753,41 -3211,1513260651626,35 -3212,1513260788865,28 -3213,1513260798253,22 -3214,1513260985331,22 -3215,1513261018705,15 -3216,1513261075942,11 -3217,1513261080076,5 -3218,1513261087492,1 -3219,1513261091758,1 -3220,1513261100095,16 -3221,1513261141570,59 -3222,1513261272088,57 -3223,1513261411177,55 -3224,1513261469501,66 -3225,1513261537807,65 -3226,1513261557511,62 -3227,1513261696266,82 -3228,1513261706980,83 -3229,1513262010234,98 -3230,1513262409302,96 -3231,1513262543691,93 -3232,1513262841540,92 -3233,1513263075865,89 -3234,1513263106585,86 -3235,1513263210285,88 -3236,1513263272209,86 -3237,1513263354086,86 -3238,1513263677918,84 -3239,1513263837526,80 -3240,1513264127426,79 -3241,1513264270454,75 -3242,1513264753400,72 -3243,1513264860253,68 -3244,1513265025028,69 -3245,1513265199560,68 -3246,1513266411771,64 -3247,1513266643462,59 -3248,1513266736530,58 -3249,1513267584715,56 -3250,1513269043232,51 -3251,1513269449578,47 -3252,1513269543240,44 -3253,1513271242912,41 -3254,1513272164802,37 -3255,1513272942260,33 -3256,1513275606642,29 -3257,1513330831420,26 -3258,1513330929013,23 -3259,1513331090053,20 -3260,1513331132427,32 -3261,1513331155602,31 -3262,1513331161924,31 -3263,1513331236914,39 -3264,1513331323194,39 -3265,1513331375356,37 -3266,1513331464472,36 -3267,1513331545500,32 -3268,1513331560325,36 -3269,1513331600424,38 -3270,1513331638011,37 -3271,1513331716749,37 -3272,1513331732697,36 -3273,1513331747624,38 -3274,1513331782735,41 -3275,1513331802960,42 -3276,1513331837403,46 -3277,1513331926495,45 -3278,1513331933986,42 -3279,1513332017449,52 -3280,1513332167013,50 -3281,1513332191275,50 -3282,1513332234448,53 -3283,1513332249961,53 -3284,1513332340989,58 -3285,1513332350233,56 -3286,1513332387512,67 -3287,1513332556425,67 -3288,1513332653361,64 -3289,1513332820648,63 -3290,1513332894926,60 -3291,1513332953424,61 -3292,1513332991470,60 -3293,1513333049049,61 -3294,1513333061504,61 -3295,1513333077456,85 -3296,1513333135228,94 -3297,1513333328432,94 -3298,1513333534905,91 -3299,1513333593004,89 -3300,1513333667871,90 -3301,1513333823993,91 -3302,1513333999082,95 -3303,1513334066825,93 -3304,1513334306269,93 -3305,1513334425653,91 -3306,1513334488876,89 -3307,1513334737134,89 -3308,1513334991848,91 -3309,1513335607807,90 -3310,1513335777324,86 -3311,1513336050234,84 -3312,1513336099663,81 -3313,1513336165732,82 -3314,1513336226796,83 -3315,1513336337396,83 -3316,1513336384957,81 -3317,1513336391740,81 -3318,1513336640574,107 -3319,1513336672997,105 -3320,1513336838813,108 -3321,1513337530678,107 -3322,1513338100091,105 -3323,1513338242443,102 -3324,1513338289251,99 -3325,1513338882750,101 -3326,1513338963605,98 -3327,1513339194681,100 -3328,1513339328175,97 -3329,1513339340462,104 -3330,1513339565085,120 -3331,1513339962781,118 -3332,1513340091996,115 -3333,1513340292658,112 -3334,1513340531747,110 -3335,1513341063030,110 -3336,1513341253825,107 -3337,1513341342465,105 -3338,1513341350022,105 -3339,1513341685101,135 -3340,1513341700366,132 -3341,1513341772511,147 -3342,1513341929761,148 -3343,1513343049766,145 -3344,1513343107508,141 -3345,1513343363550,142 -3346,1513344039007,138 -3347,1513344450939,133 -3348,1513345343870,130 -3349,1513345416444,125 -3350,1513345474667,125 -3351,1513345484207,124 -3352,1513345649018,149 -3353,1513345867437,147 -3354,1513345999575,143 -3355,1513346259037,139 -3356,1513346697112,134 -3357,1513347597352,129 -3358,1513347762828,123 -3359,1513347792476,119 -3360,1513347898958,123 -3361,1513347928648,121 -3362,1513348137756,126 -3363,1513348142122,127 -3364,1513348574943,191 -3365,1513349398716,185 -3366,1513349468021,179 -3367,1513350061459,179 -3368,1513350287428,173 -3369,1513350430693,170 -3370,1513350470093,168 -3371,1513350564716,172 -3372,1513350690586,170 -3373,1513350700302,168 -3374,1513350730662,206 -3375,1513350901249,215 -3376,1513351781895,213 -3377,1513352057503,207 -3378,1513352306026,201 -3379,1513352479670,202 -3380,1513352542882,198 -3381,1513352644370,198 -3382,1513353171701,197 -3383,1513353475466,192 -3384,1513353689381,189 -3385,1513354078437,184 -3386,1513354175144,185 -3387,1513354774686,184 -3388,1513354956387,178 -3389,1513355299931,174 -3390,1513355360837,168 -3391,1513355953202,167 -3392,1513356486650,162 -3393,1513356696557,157 -3394,1513356745837,152 -3395,1513356967934,158 -3396,1513357058009,158 -3397,1513357136380,158 -3398,1513357398307,156 -3399,1513357626953,150 -3400,1513357866130,146 -3401,1513358100691,142 -3402,1513358129723,136 -3403,1513358256233,141 -3404,1513358368506,138 -3405,1513358456224,133 -3406,1513358467098,131 -3407,1513358650602,154 -3408,1513358702638,147 -3409,1513358986442,147 -3410,1513359318746,140 -3411,1513359398237,134 -3412,1513359470340,130 -3413,1513359491398,128 -3414,1513359522982,136 -3415,1513359675933,139 -3416,1513359694104,134 -3417,1513359718559,146 -3418,1513359848468,166 -3419,1513360015541,161 -3420,1513360114744,159 -3421,1513360195362,155 -3422,1513361068262,152 -3423,1513361258595,144 -3424,1513361407318,138 -3425,1513361588562,134 -3426,1513362086709,127 -3427,1513362479946,122 -3428,1513362722105,114 -3429,1513362766080,107 -3430,1513363099986,115 -3431,1513363227042,109 -3432,1513363635101,103 -3433,1513363710833,96 -3434,1513363891138,92 -3435,1513363924676,85 -3436,1513364189635,83 -3437,1513364683103,77 -3438,1513364948970,70 -3439,1513364990023,80 -3440,1513365036247,77 -3441,1513365792464,84 -3442,1513365802456,79 -3443,1513366141722,92 -3444,1513366217238,85 -3445,1513366252953,83 -3446,1513366314948,82 -3447,1513366533803,77 -3448,1513366792486,70 -3449,1513366943516,63 -3450,1513367000166,59 -3451,1513367064161,56 -3452,1513367086123,67 -3453,1513367195670,68 -3454,1513367346730,63 -3455,1513367374653,57 -3456,1513367421343,55 -3457,1513367837163,52 -3458,1513367875706,45 -3459,1513367978012,41 -3460,1513368141491,39 -3461,1513368148404,34 -3462,1513368230085,44 -3463,1513368277092,39 -3464,1513368419283,69 -3465,1513368588534,64 -3466,1513368642407,59 -3467,1513368709218,59 -3468,1513368789775,55 -3469,1513368876273,51 -3470,1513368883271,48 -3471,1513368887334,63 -3472,1513368940202,96 -3473,1513369283818,96 -3474,1513369290363,111 -3475,1513369407334,154 -3476,1513369607012,152 -3477,1513369845579,147 -3478,1513370323544,143 -3479,1513370480416,138 -3480,1513370570510,135 -3481,1513370614936,135 -3482,1513370758197,138 -3483,1513371479523,135 -3484,1513372388162,130 -3485,1513372514893,124 -3486,1513372521886,121 -3487,1513372606448,159 -3488,1513372727243,156 -3489,1513373317967,153 -3490,1513373857226,147 -3491,1513373863790,144 -3492,1513374012408,190 -3493,1513374076939,185 -3494,1513374248285,185 -3495,1513374721256,184 -3496,1513375336099,177 -3497,1513375440443,173 -3498,1513375466956,171 -3499,1513375474762,179 -3500,1513375588054,228 -3501,1513375950620,224 -3502,1513376074141,218 -3503,1513377008004,218 -3504,1513377065618,212 -3505,1513377418658,213 -3506,1513377473065,207 -3507,1513377967305,223 -3508,1513378261238,216 -3509,1513379001772,213 -3510,1513379284926,206 -3511,1513379624656,200 -3512,1513379845776,195 -3513,1513379970991,191 -3514,1513380535132,194 -3515,1513380624132,191 -3516,1513381809331,189 -3517,1513383169348,191 -3518,1513383702573,191 -3519,1513384300957,185 -3520,1513384378304,180 -3521,1513384577184,180 -3522,1513384892582,177 -3523,1513385204789,171 -3524,1513385521241,165 -3525,1513385588265,160 -3526,1513386037642,160 -3527,1513386138928,153 -3528,1513386383001,149 -3529,1513386472750,143 -3530,1513386816920,143 -3531,1513387289662,137 -3532,1513387385134,131 -3533,1513387556333,126 -3534,1513387712403,122 -3535,1513387844601,117 -3536,1513387856802,114 -3537,1513387974619,130 -3538,1513388601584,125 -3539,1513389011568,118 -3540,1513389049308,113 -3541,1513389188868,115 -3542,1513389281569,108 -3543,1513389339510,113 -3544,1513389754020,110 -3545,1513389908480,105 -3546,1513390147050,101 -3547,1513390163195,96 -3548,1513390322181,103 -3549,1513390571676,97 -3550,1513390691784,90 -3551,1513390756640,86 -3552,1513390831892,82 -3553,1513390902371,80 -3554,1513391046064,76 -3555,1513391117983,71 -3556,1513391121971,67 -3557,1513391179109,101 -3558,1513391211694,98 -3559,1513391737001,98 -3560,1513391834305,90 -3561,1513392198778,84 -3562,1513392490894,83 -3563,1513392792975,75 -3564,1513392851411,69 -3565,1513393174592,64 -3566,1513393247503,56 -3567,1513393309635,51 -3568,1513393368004,46 -3569,1513393392745,40 -3570,1513393396924,37 -3571,1513393627927,58 -3572,1513393938522,70 -3573,1513393951012,65 -3574,1513394109378,69 -3575,1513394239772,83 -3576,1513394317848,79 -3577,1513394341305,75 -3578,1513394423365,76 -3579,1513394598765,71 -3580,1513394609156,65 -3581,1513394880464,75 -3582,1513394933028,72 -3583,1513395422529,68 -3584,1513395495395,62 -3585,1513395510860,56 -3586,1513395517544,59 -3587,1513395524228,94 -3588,1513395542078,123 -3589,1513395759313,131 -3590,1513395898994,127 -3591,1513395942735,121 -3592,1513395975428,146 -3593,1513396110334,151 -3594,1513396168306,151 -3595,1513396498685,150 -3596,1513397209272,144 -3597,1513397310235,138 -3598,1513397678072,135 -3599,1513397952485,137 -3600,1513398015775,159 -3601,1513398163250,161 -3602,1513398799231,158 -3603,1513399408831,154 -3604,1513399481338,150 -3605,1513399516138,152 -3606,1513399613546,157 -3607,1513399823163,159 -3608,1513400216549,155 -3609,1513400231570,151 -3610,1513400244129,168 -3611,1513401034043,195 -3612,1513402013791,189 -3613,1513402643716,183 -3614,1513402730169,179 -3615,1513402953290,177 -3616,1513403437598,175 -3617,1513403747541,168 -3618,1513404049658,163 -3619,1513404062336,157 -3620,1513404439288,180 -3621,1513404497759,176 -3622,1513404549824,177 -3623,1513404621651,179 -3624,1513404628320,177 -3625,1513404663597,234 -3626,1513405151670,244 -3627,1513405279387,237 -3628,1513405699246,235 -3629,1513406069993,227 -3630,1513406085644,221 -3631,1513406145780,247 -3632,1513408175915,248 -3633,1513408548002,240 -3634,1513408630728,234 -3635,1513409015013,232 -3636,1513409079153,224 -3637,1513409719830,236 -3638,1513409839966,229 -3639,1513410202059,224 -3640,1513410241533,216 -3641,1513410245396,224 -3642,1513410496517,355 -3643,1513410564037,348 -3644,1513411491137,351 -3645,1513411628198,340 -3646,1513411958291,336 -3647,1513412688919,327 -3648,1513413345472,324 -3649,1513413568511,314 -3650,1513413907825,306 -3651,1513414035003,298 -3652,1513414404120,293 -3653,1513414762535,285 -3654,1513414844099,277 -3655,1513415509590,274 -3656,1513415578396,264 -3657,1513415748460,283 -3658,1513416236935,278 -3659,1513416535811,271 -3660,1513416651305,263 -3661,1513417273290,258 -3662,1513417823452,248 -3663,1513417996157,239 -3664,1513418186222,231 -3665,1513418369978,224 -3666,1513418567803,216 -3667,1513418658056,209 -3668,1513418665002,203 -3669,1513418845227,263 -3670,1513418860392,256 -3671,1513419324896,296 -3672,1513420416020,285 -3673,1513421683467,272 -3674,1513422110242,267 -3675,1513422384574,257 -3676,1513423600055,247 -3677,1513424127804,237 -3678,1513424604639,229 -3679,1513426112141,219 -3680,1513426268719,207 -3681,1513427047646,205 -3682,1513427837653,195 -3683,1513428121379,185 -3684,1513428353544,174 -3685,1513428656183,165 -3686,1513428930729,159 -3687,1513429048902,159 -3688,1513429061325,167 -3689,1513429281662,197 -3690,1513429498076,188 -3691,1513429787751,180 -3692,1513429876809,173 -3693,1513430007301,172 -3694,1513430174869,165 -3695,1513430558083,159 -3696,1513430602835,149 -3697,1513430761433,147 -3698,1513430851591,139 -3699,1513430866691,131 -3700,1513430985864,142 -3701,1513431385607,136 -3702,1513431400696,127 -3703,1513432268543,135 -3704,1513432839892,124 -3705,1513432946701,115 -3706,1513433103525,111 -3707,1513433203923,103 -3708,1513433270503,95 -3709,1513433434469,86 -3710,1513433441064,88 -3711,1513433496193,126 -3712,1513433528082,120 -3713,1513433531850,118 -3714,1513433810241,182 -3715,1513433879715,174 -3716,1513434737533,168 -3717,1513434924762,155 -3718,1513435481504,146 -3719,1513435485576,134 -3720,1513436078305,215 -3721,1513437156030,203 -3722,1513437174844,193 -3723,1513437189955,209 -3724,1513437477774,232 -3725,1513437980247,252 -3726,1513438240400,249 -3727,1513438300655,239 -3728,1513438352888,238 -3729,1513438703995,236 -3730,1513438918767,226 -3731,1513438939577,232 -3732,1513438954641,251 -3733,1513438999099,278 -3734,1513439264413,281 -3735,1513439719118,273 -3736,1513439731665,261 -3737,1513439942888,302 -3738,1513440316157,291 -3739,1513440671768,281 -3740,1513441338113,269 -3741,1513441681978,263 -3742,1513441896022,323 -3743,1513442163025,315 -3744,1513442441322,313 -3745,1513443616646,304 -3746,1513443842656,296 -3747,1513444047978,289 -3748,1513444364262,281 -3749,1513444717346,271 -3750,1513444813958,263 -3751,1513444840010,258 -3752,1513444942179,273 -3753,1513445579699,269 -3754,1513445606760,258 -3755,1513446118305,273 -3756,1513446787144,262 -3757,1513446797038,256 -3758,1513446924038,307 -3759,1513448150537,300 -3760,1513448701894,289 -3761,1513448760300,280 -3762,1513449234764,278 -3763,1513450497901,267 -3764,1513451884591,256 -3765,1513452040499,244 -3766,1513452893885,236 -3767,1513452962336,224 -3768,1513453628623,221 -3769,1513453978662,245 -3770,1513455042317,237 -3771,1513457924190,246 -3772,1513458786185,235 -3773,1513459856235,225 -3774,1513459945962,214 -3775,1513460268589,208 -3776,1513460331984,199 -3777,1513460441975,194 -3778,1513460547380,188 -3779,1513461054358,181 -3780,1513461259478,171 -3781,1513461591756,163 -3782,1513461712265,152 -3783,1513461896474,143 -3784,1513462118958,134 -3785,1513462157016,124 -3786,1513462287416,121 -3787,1513462509851,111 -3788,1513462797353,102 -3789,1513462849347,108 -3790,1513462893106,103 -3791,1513463142242,98 -3792,1513463309505,87 -3793,1513463780156,80 -3794,1513464055749,70 -3795,1513464128789,60 -3796,1513464401748,52 -3797,1513464496929,44 -3798,1513464569172,35 -3799,1513464578767,27 -3800,1513464591448,33 -3801,1513464629866,29 -3802,1513464699824,21 -3803,1513464726117,20 -3804,1513464736023,12 -3805,1513464786084,4 -3806,1513464801898,1 -3807,1513464805708,1 -3808,1513464812253,1 -3809,1513464816084,1 -3810,1513464822681,1 -3811,1513464827357,1 -3812,1513464835208,1 -3813,1513464839089,1 -3814,1513464842933,1 -3815,1513464846680,1 -3816,1513464850446,1 -3817,1513464854349,1 -3818,1513464858379,1 -3819,1513464862162,1 -3820,1513464866081,1 -3821,1513464869918,1 -3822,1513464873897,1 -3823,1513464878014,1 -3824,1513464888675,1 -3825,1513464892274,1 -3826,1513464896120,1 -3827,1513464900069,1 -3828,1513464904044,1 -3829,1513464907854,1 -3830,1513464911845,1 -3831,1513464915548,1 -3832,1513464919386,1 -3833,1513464923339,1 -3834,1513464927296,1 -3835,1513464931319,1 -3836,1513464942798,1 -3837,1513464947175,1 -3838,1513464950932,1 -3839,1513464954683,1 -3840,1513464958505,1 -3841,1513464962705,1 -3842,1513464966667,1 -3843,1513464970549,1 -3844,1513464974779,1 -3845,1513464983473,1 -3846,1513464991291,1 -3847,1513464995626,1 -3848,1513464999375,1 -3849,1513465006472,1 -3850,1513465010462,1 -3851,1513465014246,1 -3852,1513465018079,1 -3853,1513465021920,1 -3854,1513465026302,1 -3855,1513465034055,1 -3856,1513465041578,1 -3857,1513465045464,1 -3858,1513465049413,1 -3859,1513465053456,1 -3860,1513465057245,1 -3861,1513465061011,1 -3862,1513465065808,1 -3863,1513465070081,1 -3864,1513465074172,1 -3865,1513465077849,1 -3866,1513465081633,1 -3867,1513465085539,1 -3868,1513465089458,1 -3869,1513465099578,1 -3870,1513465103529,1 -3871,1513465107263,1 -3872,1513465111091,1 -3873,1513465117625,1 -3874,1513465121445,1 -3875,1513465125417,1 -3876,1513465129318,1 -3877,1513465133347,1 -3878,1513465137654,1 -3879,1513465141525,1 -3880,1513465145557,1 -3881,1513465154036,1 -3882,1513465160766,1 -3883,1513465164673,1 -3884,1513465168690,1 -3885,1513465173256,1 -3886,1513465183725,2 -3887,1513465205671,2 -3888,1513465212249,1 -3889,1513465219347,1 -3890,1513465227001,3 -3891,1513465235223,6 -3892,1513465241922,6 -3893,1513465289160,8 -3894,1513465315499,8 -3895,1513465319399,8 -3896,1513465332660,12 -3897,1513465336538,14 -3898,1513465363261,22 -3899,1513465372675,23 -3900,1513465405313,31 -3901,1513465462118,35 -3902,1513465477974,36 -3903,1513465537320,41 -3904,1513465545728,42 -3905,1513465569716,54 -3906,1513465835729,58 -3907,1513466349602,57 -3908,1513466507013,56 -3909,1513466623009,55 -3910,1513466649854,55 -3911,1513466671747,59 -3912,1513466899957,64 -3913,1513467102555,63 -3914,1513467537105,62 -3915,1513467577920,62 -3916,1513467634770,63 -3917,1513467659025,65 -3918,1513467806618,69 -3919,1513467813607,69 -3920,1513467846233,91 -3921,1513467892528,96 -3922,1513467981371,99 -3923,1513468106063,100 -3924,1513468309558,99 -3925,1513468540486,98 -3926,1513468555603,98 -3927,1513468836316,110 -3928,1513468848869,109 -3929,1513469083296,127 -3930,1513469442582,126 -3931,1513469592109,124 -3932,1513469782513,123 -3933,1513469848082,122 -3934,1513470354152,124 -3935,1513470405524,122 -3936,1513470701278,125 -3937,1513470705135,122 -3938,1513470924348,196 -3939,1513470950871,194 -3940,1513471167110,207 -3941,1513471674134,205 -3942,1513471937985,202 -3943,1513472112346,199 -3944,1513472319017,197 -3945,1513473206830,196 -3946,1513473905743,191 -3947,1513474363693,187 -3948,1513474419300,184 -3949,1513474457703,187 -3950,1513474607603,194 -3951,1513474690343,193 -3952,1513474891594,194 -3953,1513475187411,191 -3954,1513475263159,188 -3955,1513475522704,189 -3956,1513475827653,185 -3957,1513475848340,182 -3958,1513476174003,198 -3959,1513477242186,194 -3960,1513477523606,189 -3961,1513477667036,185 -3962,1513477858833,183 -3963,1513477885225,180 -3964,1513477960439,191 -3965,1513477981306,191 -3966,1513478317859,208 -3967,1513478423102,203 -3968,1513478656264,202 -3969,1513479243739,198 -3970,1513479401200,192 -3971,1513479465444,189 -3972,1513479975093,190 -3973,1513480436976,184 -3974,1513480516035,178 -3975,1513480637672,178 -3976,1513480821637,175 -3977,1513480999697,171 -3978,1513481762149,166 -3979,1513481789510,161 -3980,1513482287076,168 -3981,1513483274511,162 -3982,1513484853875,156 -3983,1513484909325,149 -3984,1513485271335,149 -3985,1513485278548,143 -3986,1513485288127,184 -3987,1513485775343,223 -3988,1513485915909,216 -3989,1513486029167,211 -3990,1513486768868,207 -3991,1513487141229,199 -3992,1513487390791,193 -3993,1513487670246,187 -3994,1513488091605,181 -3995,1513488175459,174 -3996,1513488444653,172 -3997,1513488780117,166 -3998,1513489256141,163 -3999,1513490215447,156 -4000,1513491378086,151 -4001,1513491402145,144 -4002,1513491715027,152 -4003,1513491750054,147 -4004,1513492246468,149 -4005,1513492353824,148 -4006,1513492363093,145 -4007,1513492528561,174 -4008,1513492698530,168 -4009,1513493083653,162 -4010,1513493277326,155 -4011,1513493320474,148 -4012,1513493324335,153 -4013,1513493541870,239 -4014,1513494248693,231 -4015,1513494485425,221 -4016,1513494969878,215 -4017,1513495042080,207 -4018,1513495189956,207 -4019,1513495320996,201 -4020,1513495396653,206 -4021,1513495550963,206 -4022,1513495811979,201 -4023,1513496271566,195 -4024,1513496315478,186 -4025,1513496726955,187 -4026,1513496768168,178 -4027,1513496827090,186 -4028,1513496862533,184 -4029,1513497199194,197 -4030,1513497466586,190 -4031,1513497630476,182 -4032,1513497870406,174 -4033,1513497880077,167 -4034,1513499325707,201 -4035,1513499593927,191 -4036,1513499615392,184 -4037,1513499622099,195 -4038,1513499731890,292 -4039,1513499980632,289 -4040,1513500425234,290 -4041,1513501265285,283 -4042,1513501568057,273 -4043,1513501615982,265 -4044,1513501652925,269 -4045,1513503674421,277 -4046,1513504215439,266 -4047,1513505010739,256 -4048,1513505715614,247 -4049,1513506102546,241 -4050,1513506761764,237 -4051,1513507418211,229 -4052,1513507607934,222 -4053,1513508667541,215 -4054,1513508978299,205 -4055,1513509725974,199 -4056,1513511080480,190 -4057,1513511240636,181 -4058,1513511592989,184 -4059,1513512232994,176 -4060,1513513074939,165 -4061,1513513465836,156 -4062,1513513543774,149 -4063,1513513610111,144 -4064,1513513698121,147 -4065,1513514232031,145 -4066,1513515753089,146 -4067,1513515768282,138 -4068,1513515800630,152 -4069,1513515958758,154 -4070,1513516097556,147 -4071,1513516135997,140 -4072,1513516516025,143 -4073,1513516677221,134 -4074,1513516759681,126 -4075,1513516911619,122 -4076,1513516987154,116 -4077,1513517100177,110 -4078,1513517232216,104 -4079,1513517238994,96 -4080,1513517271384,127 -4081,1513517309056,126 -4082,1513517806770,124 -4083,1513517822415,113 -4084,1513518891021,123 -4085,1513519099138,113 -4086,1513519233020,128 -4087,1513519379221,144 -4088,1513519520949,137 -4089,1513519657098,132 -4090,1513519797670,127 -4091,1513519838719,120 -4092,1513519901736,118 -4093,1513519984889,114 -4094,1513520063722,108 -4095,1513520173215,102 -4096,1513520191389,97 -4097,1513520667032,100 -4098,1513520790632,92 -4099,1513521276893,85 -4100,1513521463856,75 -4101,1513521536254,66 -4102,1513521549152,66 -4103,1513521564303,70 -4104,1513521585378,75 -4105,1513521603988,74 -4106,1513521636067,76 -4107,1513521743662,91 -4108,1513521946244,84 -4109,1513522211975,77 -4110,1513522244136,68 -4111,1513522253541,65 -4112,1513522260678,76 -4113,1513522484266,141 -4114,1513522556939,136 -4115,1513523053721,131 -4116,1513523159046,125 -4117,1513523171795,119 -4118,1513523878147,136 -4119,1513524094224,129 -4120,1513524114953,123 -4121,1513524208276,132 -4122,1513524420393,128 -4123,1513524699232,122 -4124,1513524762954,114 -4125,1513524951816,114 -4126,1513525064646,108 -4127,1513525294884,106 -4128,1513525346720,102 -4129,1513525361857,105 -4130,1513525391995,114 -4131,1513525509335,115 -4132,1513525550880,110 -4133,1513525645054,108 -4134,1513525794302,123 -4135,1513525960827,117 -4136,1513526012319,111 -4137,1513526119804,118 -4138,1513526165887,149 -4139,1513526983793,153 -4140,1513527013852,147 -4141,1513527237079,153 -4142,1513527358234,147 -4143,1513527466467,144 -4144,1513527553040,147 -4145,1513527582761,152 -4146,1513527690893,157 -4147,1513527939526,154 -4148,1513528025589,150 -4149,1513528269404,147 -4150,1513528553612,142 -4151,1513528660020,136 -4152,1513528956659,132 -4153,1513529011290,127 -4154,1513529159272,125 -4155,1513529419222,121 -4156,1513529640756,115 -4157,1513529899209,109 -4158,1513530085409,104 -4159,1513530387590,99 -4160,1513530796682,92 -4161,1513531369310,85 -4162,1513531430412,79 -4163,1513531466782,77 -4164,1513531555762,77 -4165,1513531645900,74 -4166,1513531649684,70 -4167,1513531802827,107 -4168,1513531856683,112 -4169,1513532106151,115 -4170,1513532479197,109 -4171,1513532488888,103 -4172,1513532509644,126 -4173,1513532705069,133 -4174,1513532739761,128 -4175,1513532877634,131 -4176,1513533093309,125 -4177,1513533131203,121 -4178,1513533189417,122 -4179,1513533775058,119 -4180,1513533833802,130 -4181,1513533915502,132 -4182,1513534045908,132 -4183,1513534236598,128 -4184,1513534304437,131 -4185,1513534621383,128 -4186,1513534654326,122 -4187,1513535082047,124 -4188,1513535234491,119 -4189,1513535338566,114 -4190,1513535379216,111 -4191,1513535691148,111 -4192,1513536120627,108 -4193,1513536369916,104 -4194,1513536394276,99 -4195,1513536475441,103 -4196,1513536569181,99 -4197,1513536586850,101 -4198,1513536591047,107 -4199,1513536839764,162 -4200,1513537073737,156 -4201,1513537724082,149 -4202,1513537877262,143 -4203,1513538299282,142 -4204,1513538334186,141 -4205,1513538855367,147 -4206,1513539074592,144 -4207,1513539125026,141 -4208,1513539438518,140 -4209,1513539810906,134 -4210,1513540123798,128 -4211,1513540141712,123 -4212,1513540377117,140 -4213,1513540440570,146 -4214,1513540697557,146 -4215,1513540983584,142 -4216,1513541734669,135 -4217,1513541858249,130 -4218,1513541973184,136 -4219,1513542010868,132 -4220,1513542028791,133 -4221,1513542110144,151 -4222,1513542176808,150 -4223,1513542354051,148 -4224,1513542380752,144 -4225,1513542433418,151 -4226,1513542465452,151 -4227,1513542908833,157 -4228,1513542978827,150 -4229,1513543417058,149 -4230,1513543449033,151 -4231,1513543671993,159 -4232,1513544247077,155 -4233,1513544415688,151 -4234,1513544644661,147 -4235,1513544672029,141 -4236,1513544779532,147 -4237,1513544836635,145 -4238,1513544843458,145 -4239,1513545152586,193 -4240,1513545303138,186 -4241,1513545412493,186 -4242,1513545613661,183 -4243,1513545779109,178 -4244,1513545942755,174 -4245,1513546146602,170 -4246,1513546826275,170 -4247,1513547178603,165 -4248,1513547346792,159 -4249,1513547507685,154 -4250,1513547512044,149 -4251,1513547516519,224 -4252,1513548231531,336 -4253,1513548985057,327 -4254,1513550084018,319 -4255,1513550812850,310 -4256,1513551057676,301 -4257,1513551495832,294 -4258,1513551534260,285 -4259,1513551710397,293 -4260,1513552081492,285 -4261,1513553441660,276 -4262,1513553579082,265 -4263,1513553594748,260 -4264,1513554237749,292 -4265,1513554392613,281 -4266,1513554910560,275 -4267,1513555166384,287 -4268,1513555454469,279 -4269,1513555584220,273 -4270,1513556744353,267 -4271,1513556774138,257 -4272,1513556813536,280 -4273,1513556927551,293 -4274,1513557381809,289 -4275,1513557775169,284 -4276,1513557813001,275 -4277,1513558548479,282 -4278,1513558585888,275 -4279,1513558797101,284 -4280,1513558852599,276 -4281,1513559333693,279 -4282,1513559670653,271 -4283,1513560011314,263 -4284,1513560090856,253 -4285,1513560242418,252 -4286,1513560249537,244 -4287,1513560598485,320 -4288,1513560937390,310 -4289,1513561209800,300 -4290,1513561305620,291 -4291,1513561796612,289 -4292,1513562306607,278 -4293,1513562608259,266 -4294,1513563099492,256 -4295,1513565003897,249 -4296,1513565159061,239 -4297,1513565415799,230 -4298,1513565765647,227 -4299,1513566201975,247 -4300,1513566251114,238 -4301,1513566338171,239 -4302,1513567108220,234 -4303,1513567979177,223 -4304,1513570039151,213 -4305,1513570100278,206 -4306,1513570320389,203 -4307,1513570966341,194 -4308,1513571621713,186 -4309,1513571677612,175 -4310,1513572348721,172 -4311,1513573070211,161 -4312,1513573497655,158 -4313,1513573615645,148 -4314,1513574248793,142 -4315,1513574382793,132 -4316,1513574484372,124 -4317,1513574696663,115 -4318,1513574731174,105 -4319,1513574761166,103 -4320,1513574819100,104 -4321,1513574990472,105 -4322,1513575083636,97 -4323,1513575110703,92 -4324,1513575142986,89 -4325,1513575155225,91 -4326,1513575287317,101 -4327,1513575412199,97 -4328,1513575469118,88 -4329,1513575700995,83 -4330,1513575871581,73 -4331,1513576297183,69 -4332,1513576309717,58 -4333,1513576465139,58 -4334,1513576582405,49 -4335,1513576646631,39 -4336,1513576682265,36 -4337,1513576868247,28 -4338,1513576895384,21 -4339,1513576929123,38 -4340,1513577010376,31 -4341,1513577036862,24 -4342,1513577075095,18 -4343,1513577090632,10 -4344,1513577109621,2 -4345,1513577122155,1 -4346,1513577126261,1 -4347,1513577130053,1 -4348,1513577137390,1 -4349,1513577141212,1 -4350,1513577145289,1 -4351,1513577149193,1 -4352,1513577152927,35 -4353,1513577159532,51 -4354,1513577296442,62 -4355,1513577380406,56 -4356,1513577395402,50 -4357,1513577539437,52 -4358,1513577571672,47 -4359,1513577635153,52 -4360,1513577945433,48 -4361,1513577980564,42 -4362,1513578046383,37 -4363,1513578056343,33 -4364,1513578060133,54 -4365,1513578123861,82 -4366,1513578160254,79 -4367,1513578265341,78 -4368,1513578302761,74 -4369,1513578333841,73 -4370,1513578494845,72 -4371,1513578501893,66 -4372,1513578818355,92 -4373,1513578859487,94 -4374,1513578998358,95 -4375,1513579113656,90 -4376,1513579157591,85 -4377,1513579310597,92 -4378,1513579366468,87 -4379,1513579405013,92 -4380,1513579746771,92 -4381,1513579765245,92 -4382,1513579830841,98 -4383,1513579969142,95 -4384,1513580113044,91 -4385,1513580269989,90 -4386,1513580361811,86 -4387,1513580638483,124 -4388,1513580792360,120 -4389,1513580843484,117 -4390,1513580903864,119 -4391,1513581007226,122 -4392,1513581146475,120 -4393,1513581557376,116 -4394,1513581595296,113 -4395,1513581725223,115 -4396,1513581782246,111 -4397,1513581818084,112 -4398,1513582221221,115 -4399,1513582276360,111 -4400,1513582401718,110 -4401,1513582405924,113 -4402,1513582460944,174 -4403,1513582798738,176 -4404,1513583172413,170 -4405,1513583182148,165 -4406,1513583427149,203 -4407,1513583690312,199 -4408,1513584828099,194 -4409,1513585129078,187 -4410,1513586006857,185 -4411,1513586503970,178 -4412,1513586544616,173 -4413,1513586594702,176 -4414,1513586719492,179 -4415,1513587418115,175 -4416,1513588458489,170 -4417,1513588633149,164 -4418,1513588707569,160 -4419,1513589039213,161 -4420,1513589305695,159 -4421,1513589520883,156 -4422,1513589959312,151 -4423,1513590441892,145 -4424,1513590957544,143 -4425,1513590973761,140 -4426,1513591276427,163 -4427,1513591555675,158 -4428,1513591783085,154 -4429,1513592028833,151 -4430,1513592247071,145 -4431,1513592287266,140 -4432,1513592446766,141 -4433,1513592585600,142 -4434,1513592590058,138 -4435,1513593220280,206 -4436,1513593387148,199 -4437,1513593835206,195 -4438,1513593926188,189 -4439,1513594375954,187 -4440,1513594402440,180 -4441,1513595157503,189 -4442,1513595306560,183 -4443,1513595433407,178 -4444,1513595453826,173 -4445,1513595644420,185 -4446,1513595994250,179 -4447,1513596082750,171 -4448,1513596154907,168 -4449,1513596233941,165 -4450,1513596678368,161 -4451,1513596969683,154 -4452,1513597770660,146 -4453,1513598119340,149 -4454,1513598491787,151 -4455,1513598751146,144 -4456,1513598962557,138 -4457,1513599081613,135 -4458,1513599209880,130 -4459,1513599296481,126 -4460,1513599429535,122 -4461,1513599722582,116 -4462,1513600102696,110 -4463,1513600121062,103 -4464,1513600370055,112 -4465,1513600513258,123 -4466,1513600743716,118 -4467,1513600786411,114 -4468,1513600947346,114 -4469,1513601058097,110 -4470,1513601087876,107 -4471,1513601184629,109 -4472,1513601635725,115 -4473,1513601639974,109 -4474,1513602239468,165 -4475,1513602402521,158 -4476,1513602580317,153 -4477,1513603229715,149 -4478,1513603379774,142 -4479,1513603655568,137 -4480,1513603710138,133 -4481,1513603943958,132 -4482,1513604908467,131 -4483,1513604957972,125 -4484,1513605025430,123 -4485,1513605033091,121 -4486,1513605936815,151 -4487,1513606123718,143 -4488,1513606456182,137 -4489,1513606889718,130 -4490,1513606896658,125 -4491,1513607046998,162 -4492,1513607256115,157 -4493,1513607259952,150 -4494,1513607479566,234 -4495,1513607720380,230 -4496,1513608389209,223 -4497,1513608687169,216 -4498,1513608697479,211 -4499,1513608781931,249 -4500,1513611020184,248 -4501,1513613280540,238 -4502,1513613317520,260 -4503,1513613425187,271 -4504,1513613829733,267 -4505,1513614241187,258 -4506,1513614467796,271 -4507,1513616437274,264 -4508,1513617414741,256 -4509,1513617571018,246 -4510,1513617609094,241 -4511,1513617900810,247 -4512,1513618634765,239 -4513,1513618951122,235 -4514,1513619222155,231 -4515,1513619583581,225 -4516,1513620249561,217 -4517,1513620788480,208 -4518,1513621499281,200 -4519,1513621673381,193 -4520,1513622478645,187 -4521,1513622506244,179 -4522,1513622627193,184 -4523,1513622665129,179 -4524,1513622682416,180 -4525,1513623135714,195 -4526,1513623224138,197 -4527,1513623492511,192 -4528,1513623835957,184 -4529,1513623941172,175 -4530,1513623948509,170 -4531,1513623980721,216 -4532,1513624259555,225 -4533,1513624279094,217 -4534,1513624419197,234 -4535,1513625203865,264 -4536,1513625735831,254 -4537,1513626736946,247 -4538,1513627390564,237 -4539,1513627444794,230 -4540,1513628026176,229 -4541,1513628272808,228 -4542,1513628315851,221 -4543,1513628948572,224 -4544,1513629377724,215 -4545,1513629701761,217 -4546,1513630238089,210 -4547,1513630738488,201 -4548,1513630955024,194 -4549,1513631062416,188 -4550,1513631349671,185 -4551,1513631557000,177 -4552,1513631644821,168 -4553,1513631746467,164 -4554,1513631790874,158 -4555,1513631827064,157 -4556,1513631843296,157 -4557,1513632154430,171 -4558,1513632890926,163 -4559,1513633054721,154 -4560,1513633131117,147 -4561,1513633523262,142 -4562,1513633641887,132 -4563,1513634119334,124 -4564,1513634174666,120 -4565,1513634346083,116 -4566,1513634592524,108 -4567,1513634742028,99 -4568,1513634776960,93 -4569,1513634944623,90 -4570,1513635190572,82 -4571,1513635234601,76 -4572,1513635288890,70 -4573,1513635326875,64 -4574,1513635457181,89 -4575,1513635789413,81 -4576,1513635826619,73 -4577,1513635882022,68 -4578,1513636132371,62 -4579,1513636174649,54 -4580,1513636178726,47 -4581,1513636238463,69 -4582,1513636370755,62 -4583,1513636526897,53 -4584,1513636571091,47 -4585,1513636676599,41 -4586,1513636857248,52 -4587,1513636868904,43 -4588,1513636961315,44 -4589,1513637191330,35 -4590,1513637195542,26 -4591,1513637237997,53 -4592,1513637247998,49 -4593,1513637282253,52 -4594,1513637355337,95 -4595,1513637372981,91 -4596,1513637903388,96 -4597,1513638486542,89 -4598,1513638519056,82 -4599,1513638646053,106 -4600,1513638659444,104 -4601,1513638731425,115 -4602,1513638910413,111 -4603,1513638957824,114 -4604,1513639008440,115 -4605,1513639026880,114 -4606,1513639120695,121 -4607,1513639168402,118 -4608,1513639462683,116 -4609,1513639498772,110 -4610,1513639878495,112 -4611,1513640151494,112 -4612,1513640322034,107 -4613,1513640329286,100 -4614,1513640337389,126 -4615,1513640717575,156 -4616,1513640750626,150 -4617,1513641082499,152 -4618,1513641087227,145 -4619,1513641696123,210 -4620,1513641703034,203 -4621,1513642165109,263 -4622,1513642728677,262 -4623,1513643090615,254 -4624,1513643484205,251 -4625,1513643810117,255 -4626,1513644546330,246 -4627,1513644679520,240 -4628,1513644720170,235 -4629,1513645020704,239 -4630,1513645292949,232 -4631,1513645684403,253 -4632,1513645787683,253 -4633,1513646097418,251 -4634,1513646397892,257 -4635,1513646517216,251 -4636,1513648945124,248 -4637,1513649324252,240 -4638,1513650240109,233 -4639,1513651198332,225 -4640,1513651393456,221 -4641,1513651516066,215 -4642,1513651573321,212 -4643,1513651762752,218 -4644,1513651873514,212 -4645,1513652327367,209 -4646,1513653462546,201 -4647,1513654656469,194 -4648,1513654660579,185 -4649,1513654838346,285 -4650,1513655808168,281 -4651,1513657434610,271 -4652,1513659315699,263 -4653,1513659651673,255 -4654,1513659722837,248 -4655,1513659755918,250 -4656,1513659764669,264 -4657,1513660251659,337 -4658,1513660576580,329 -4659,1513660911132,320 -4660,1513661915457,312 -4661,1513662693345,304 -4662,1513663538626,294 -4663,1513664381462,284 -4664,1513665309701,274 -4665,1513666351762,267 -4666,1513667903916,256 -4667,1513669024212,247 -4668,1513669538828,237 -4669,1513672993952,230 -4670,1513676368579,219 -4671,1513677089129,209 -4672,1513677193627,200 -4673,1513677862307,196 -4674,1513677964948,187 -4675,1513678246075,181 -4676,1513680357915,173 -4677,1513680560416,164 -4678,1513681176971,157 -4679,1513681443798,147 -4680,1513681451014,138 -4681,1513681928624,188 -4682,1513682458669,179 -4683,1513682480998,170 -4684,1513682568067,177 -4685,1513682623064,171 -4686,1513682708909,168 -4687,1513682833806,161 -4688,1513683533923,157 -4689,1513683595293,147 -4690,1513683792308,142 -4691,1513683918041,139 -4692,1513684264303,131 -4693,1513684285255,128 -4694,1513684630510,133 -4695,1513684735861,124 -4696,1513684914674,122 -4697,1513685102211,112 -4698,1513685265072,103 -4699,1513685400475,96 -4700,1513685498513,87 -4701,1513685854637,88 -4702,1513686133768,80 -4703,1513686149927,70 -4704,1513686208873,72 -4705,1513686417792,67 -4706,1513686519839,64 -4707,1513686735658,58 -4708,1513686796385,50 -4709,1513686809974,42 -4710,1513686838696,42 -4711,1513687034147,36 -4712,1513687069096,26 -4713,1513687134677,18 -4714,1513687139463,25 -4715,1513687207546,47 -4716,1513687284150,39 -4717,1513687378716,36 -4718,1513687490202,28 -4719,1513687626323,57 -4720,1513687683258,50 -4721,1513687717521,80 -4722,1513687783756,79 -4723,1513688300913,74 -4724,1513688787983,67 -4725,1513688812514,61 -4726,1513689017608,61 -4727,1513689226010,55 -4728,1513689239401,49 -4729,1513689311008,58 -4730,1513689422352,53 -4731,1513689426509,48 -4732,1513689460993,69 -4733,1513689728503,69 -4734,1513689780419,62 -4735,1513690024093,58 -4736,1513690144279,54 -4737,1513690259657,47 -4738,1513690279945,41 -4739,1513690372641,39 -4740,1513690471363,33 -4741,1513690566740,27 -4742,1513690679584,22 -4743,1513690792135,19 -4744,1513690812198,13 -4745,1513690822260,10 -4746,1513690829810,5 -4747,1513690858828,1 -4748,1513690862908,1 -4749,1513690867048,40 -4750,1513690870966,60 -4751,1513690972092,90 -4752,1513691015690,85 -4753,1513691022768,84 -4754,1513691036035,107 -4755,1513691058729,122 -4756,1513691065951,137 -4757,1513691446170,213 -4758,1513691557250,208 -4759,1513691761293,207 -4760,1513691861554,203 -4761,1513692346059,201 -4762,1513692393621,196 -4763,1513692479282,199 -4764,1513692840782,198 -4765,1513693258910,192 -4766,1513693357534,186 -4767,1513694089096,184 -4768,1513694471503,177 -4769,1513694869972,172 -4770,1513695267855,165 -4771,1513695354950,159 -4772,1513695400377,156 -4773,1513695454999,159 -4774,1513696039181,159 -4775,1513696673083,154 -4776,1513696792829,149 -4777,1513696924268,144 -4778,1513697191809,140 -4779,1513697541434,134 -4780,1513697662758,128 -4781,1513697887557,147 -4782,1513698009181,142 -4783,1513698198510,138 -4784,1513698360352,142 -4785,1513698490974,140 -4786,1513698658553,140 -4787,1513698662659,138 -4788,1513698946692,213 -4789,1513698950652,207 -4790,1513699058493,328 -4791,1513699445934,327 -4792,1513699732264,321 -4793,1513699936690,315 -4794,1513700300752,316 -4795,1513700605881,309 -4796,1513700653422,303 -4797,1513700874350,309 -4798,1513701122154,304 -4799,1513701556880,298 -4800,1513701791452,291 -4801,1513702138919,285 -4802,1513703446865,278 -4803,1513703564925,269 -4804,1513704139731,270 -4805,1513704869373,263 -4806,1513705813976,254 -4807,1513706066029,246 -4808,1513706195308,239 -4809,1513706567207,234 -4810,1513706589724,230 -4811,1513706889315,247 -4812,1513707139314,240 -4813,1513707458695,232 -4814,1513707573955,225 -4815,1513707706537,226 -4816,1513707875299,221 -4817,1513708302408,214 -4818,1513708402846,207 -4819,1513708701115,201 -4820,1513708932364,194 -4821,1513709734200,186 -4822,1513709996301,179 -4823,1513710196824,173 -4824,1513710622030,164 -4825,1513710829471,156 -4826,1513711262955,151 -4827,1513711279936,143 -4828,1513711396818,153 -4829,1513711730920,151 -4830,1513711889798,142 -4831,1513711900035,135 -4832,1513712046491,171 -4833,1513712191801,166 -4834,1513712575603,159 -4835,1513712619258,151 -4836,1513713046816,149 -4837,1513713147957,141 -4838,1513713206475,134 -4839,1513713345195,131 -4840,1513713492162,124 -4841,1513713992282,116 -4842,1513714432353,107 -4843,1513714707223,97 -4844,1513714844147,88 -4845,1513715103562,80 -4846,1513715456580,71 -4847,1513715526124,63 -4848,1513715567022,54 -4849,1513715595671,47 -4850,1513715691827,53 -4851,1513715794492,63 -4852,1513715894655,56 -4853,1513715975988,50 -4854,1513716088692,56 -4855,1513716228488,58 -4856,1513716298544,58 -4857,1513716329077,74 -4858,1513716368082,73 -4859,1513716382509,71 -4860,1513716401789,76 -4861,1513716464083,80 -4862,1513716516632,76 -4863,1513716775260,76 -4864,1513717027185,71 -4865,1513717082497,64 -4866,1513717187896,60 -4867,1513717270863,55 -4868,1513717407503,48 -4869,1513717451004,42 -4870,1513717506001,37 -4871,1513717513792,31 -4872,1513717528402,35 -4873,1513717597710,37 -4874,1513717669266,33 -4875,1513717731575,26 -4876,1513717751873,19 -4877,1513717765128,16 -4878,1513717775959,12 -4879,1513717801910,6 -4880,1513717831273,1 -4881,1513717836331,1 -4882,1513717844511,1 -4883,1513717848573,1 -4884,1513717852727,1 -4885,1513717857185,1 -4886,1513717861303,1 -4887,1513717865396,1 -4888,1513717869707,1 -4889,1513717873745,1 -4890,1513717877867,42 -4891,1513717943249,65 -4892,1513718016554,63 -4893,1513718174180,62 -4894,1513718209444,59 -4895,1513718225210,60 -4896,1513718279918,64 -4897,1513718338975,70 -4898,1513718452984,70 -4899,1513718526914,68 -4900,1513718613320,66 -4901,1513718689140,65 -4902,1513718841259,62 -4903,1513719019560,59 -4904,1513719104893,57 -4905,1513719357271,55 -4906,1513719376905,51 -4907,1513719472086,53 -4908,1513719476739,50 -4909,1513719613562,73 -4910,1513719690195,70 -4911,1513719717239,79 -4912,1513719861137,81 -4913,1513719993869,80 -4914,1513720097144,78 -4915,1513720131817,77 -4916,1513720165053,79 -4917,1513720257630,81 -4918,1513720382093,80 -4919,1513720701929,79 -4920,1513720958285,76 -4921,1513721098517,72 -4922,1513721145075,68 -4923,1513721277985,67 -4924,1513721368178,65 -4925,1513721372643,62 -4926,1513721495294,91 -4927,1513721569417,89 -4928,1513721974425,96 -4929,1513722122224,93 -4930,1513722188701,90 -4931,1513722399533,89 -4932,1513722687421,102 -4933,1513722844976,100 -4934,1513722968697,97 -4935,1513722985115,95 -4936,1513723060758,108 -4937,1513723141014,107 -4938,1513723333449,108 -4939,1513723813684,107 -4940,1513723831612,105 -4941,1513724033802,115 -4942,1513724325840,111 -4943,1513724329888,108 -4944,1513724342745,168 -4945,1513724734639,193 -4946,1513724922184,189 -4947,1513725351804,185 -4948,1513725850027,181 -4949,1513725902749,177 -4950,1513725969960,181 -4951,1513726088740,182 -4952,1513726559663,180 -4953,1513726787074,175 -4954,1513726857962,171 -4955,1513727033064,171 -4956,1513727061660,167 -4957,1513727457578,176 -4958,1513727517225,173 -4959,1513727761934,175 -4960,1513727835387,176 -4961,1513728073082,181 -4962,1513728429240,177 -4963,1513728645048,174 -4964,1513728821639,170 -4965,1513729297890,166 -4966,1513729317123,161 -4967,1513729572925,176 -4968,1513729592825,172 -4969,1513729996971,186 -4970,1513730061345,181 -4971,1513730373310,182 -4972,1513731002885,181 -4973,1513731177166,178 -4974,1513731304383,174 -4975,1513731350428,171 -4976,1513731399815,174 -4977,1513731805482,176 -4978,1513731889872,171 -4979,1513732527357,170 -4980,1513732699025,164 -4981,1513732909092,160 -4982,1513733004162,154 -4983,1513733133468,151 -4984,1513733330724,147 -4985,1513733600967,142 -4986,1513733880228,135 -4987,1513734074355,130 -4988,1513734088119,124 -4989,1513734279146,139 -4990,1513734354249,133 -4991,1513734729876,143 -4992,1513735139481,137 -4993,1513735374033,132 -4994,1513735411845,126 -4995,1513735572520,129 -4996,1513735935628,128 -4997,1513736036835,123 -4998,1513736273940,120 -4999,1513736457743,114 -5000,1513736545281,111 -5001,1513736658808,107 -5002,1513736726193,103 -5003,1513736869967,100 -5004,1513736909036,94 -5005,1513737029962,94 -5006,1513737136261,88 -5007,1513737255101,86 -5008,1513737376040,81 -5009,1513737490019,89 -5010,1513737724609,84 -5011,1513737777037,80 -5012,1513738369956,80 -5013,1513738424176,74 -5014,1513738459455,71 -5015,1513738698217,69 -5016,1513738838710,66 -5017,1513738879887,63 -5018,1513738944623,60 -5019,1513739055405,56 -5020,1513739214822,52 -5021,1513739478827,46 -5022,1513739489364,40 -5023,1513739563386,44 -5024,1513739604012,39 -5025,1513739683477,35 -5026,1513739738781,47 -5027,1513740044286,42 -5028,1513740124299,39 -5029,1513740150438,33 -5030,1513740169484,31 -5031,1513740299372,29 -5032,1513740357286,24 -5033,1513740504572,19 -5034,1513740512320,14 -5035,1513740516494,13 -5036,1513740575989,20 -5037,1513740586051,17 -5038,1513740593417,16 -5039,1513740603379,15 -5040,1513740613270,13 -5041,1513740617522,17 -5042,1513740661982,21 -5043,1513740669144,16 -5044,1513740713530,48 -5045,1513740968730,61 -5046,1513741075268,57 -5047,1513741168130,55 -5048,1513741291460,51 -5049,1513741599936,47 -5050,1513741719425,46 -5051,1513741755351,46 -5052,1513741954878,46 -5053,1513741983141,42 -5054,1513742151027,42 -5055,1513742179265,40 -5056,1513742287556,40 -5057,1513742378680,43 -5058,1513742456303,40 -5059,1513742535933,41 -5060,1513742543144,38 -5061,1513742601276,49 -5062,1513742852247,47 -5063,1513742973872,44 -5064,1513742989334,40 -5065,1513743163791,43 -5066,1513743363905,40 -5067,1513743398574,46 -5068,1513743429880,45 -5069,1513743454549,55 -5070,1513743459240,57 -5071,1513743609458,85 -5072,1513743656131,83 -5073,1513743696844,83 -5074,1513743780190,85 -5075,1513743845753,84 -5076,1513743971530,87 -5077,1513744001869,88 -5078,1513744140642,92 -5079,1513744413093,91 -5080,1513744445106,88 -5081,1513744514423,90 -5082,1513744703580,90 -5083,1513744860008,89 -5084,1513745212544,87 -5085,1513745473303,84 -5086,1513745515747,81 -5087,1513745538212,82 -5088,1513745856574,87 -5089,1513745930821,94 -5090,1513746186290,93 -5091,1513746689980,92 -5092,1513746819826,88 -5093,1513746919180,86 -5094,1513746926919,84 -5095,1513747049414,110 -5096,1513747318084,109 -5097,1513747755515,106 -5098,1513748086688,103 -5099,1513748096885,100 -5100,1513748323946,120 -5101,1513748451623,117 -5102,1513748534190,116 -5103,1513748639527,116 -5104,1513748708172,115 -5105,1513748821386,117 -5106,1513749005847,116 -5107,1513749030895,114 -5108,1513749164521,120 -5109,1513749189724,118 -5110,1513749491799,126 -5111,1513749715624,122 -5112,1513750042242,120 -5113,1513750058824,115 -5114,1513750172441,128 -5115,1513750262965,129 -5116,1513750501842,127 -5117,1513750748035,124 -5118,1513750927584,122 -5119,1513750947015,119 -5120,1513751423512,129 -5121,1513751484181,124 -5122,1513751527590,124 -5123,1513751577757,130 -5124,1513751731047,132 -5125,1513752342241,129 -5126,1513752775033,125 -5127,1513752912632,121 -5128,1513753230787,117 -5129,1513753408655,113 -5130,1513753452423,111 -5131,1513753769460,113 -5132,1513754450237,109 -5133,1513754730189,104 -5134,1513755266954,100 -5135,1513755424545,97 -5136,1513755734163,96 -5137,1513756109092,92 -5138,1513756370268,88 -5139,1513756382928,87 -5140,1513756433641,101 -5141,1513756594006,101 -5142,1513756929523,102 -5143,1513757016382,98 -5144,1513757410626,98 -5145,1513757692582,94 -5146,1513757721245,90 -5147,1513757743983,93 -5148,1513757936736,98 -5149,1513758014591,94 -5150,1513758209520,92 -5151,1513758510660,87 -5152,1513758659344,84 -5153,1513758803373,81 -5154,1513758847669,78 -5155,1513758931209,77 -5156,1513759027582,76 -5157,1513759036125,72 -5158,1513759075144,87 -5159,1513759234889,87 -5160,1513759446963,83 -5161,1513759589974,85 -5162,1513759815630,82 -5163,1513760124705,76 -5164,1513760234911,72 -5165,1513760368573,71 -5166,1513760419002,67 -5167,1513760453727,64 -5168,1513760526953,64 -5169,1513760721293,63 -5170,1513760765867,60 -5171,1513760819334,73 -5172,1513760861533,71 -5173,1513761002629,72 -5174,1513761236973,70 -5175,1513761406890,68 -5176,1513761634555,65 -5177,1513761645067,61 -5178,1513761689204,73 -5179,1513761802073,72 -5180,1513761910621,69 -5181,1513762247747,69 -5182,1513762269282,66 -5183,1513762435483,69 -5184,1513762462265,64 -5185,1513762478821,66 -5186,1513762620362,70 -5187,1513762844327,68 -5188,1513762925054,67 -5189,1513763009637,65 -5190,1513763052870,63 -5191,1513763087630,62 -5192,1513763137378,60 -5193,1513763256364,59 -5194,1513763285323,56 -5195,1513763289765,68 -5196,1513763348157,100 -5197,1513763484864,100 -5198,1513763550222,96 -5199,1513763741974,94 -5200,1513763749337,102 -5201,1513763753889,131 -5202,1513764208678,194 -5203,1513764415033,190 -5204,1513764637166,187 -5205,1513764698572,184 -5206,1513765354866,185 -5207,1513765424652,180 -5208,1513765828852,185 -5209,1513765872193,180 -5210,1513766395446,189 -5211,1513766636531,184 -5212,1513766841351,180 -5213,1513766878540,175 -5214,1513767029327,188 -5215,1513767059087,186 -5216,1513767501281,196 -5217,1513767923107,191 -5218,1513768038929,186 -5219,1513768391467,183 -5220,1513768626246,185 -5221,1513768752018,181 -5222,1513768816200,180 -5223,1513769430743,183 -5224,1513769715636,180 -5225,1513770352980,176 -5226,1513770644259,171 -5227,1513770651473,165 -5228,1513770710872,214 -5229,1513771193483,216 -5230,1513771253228,210 -5231,1513771387215,214 -5232,1513771410657,211 -5233,1513771832610,225 -5234,1513772997012,218 -5235,1513773047028,212 -5236,1513773408290,215 -5237,1513773856680,208 -5238,1513774618825,201 -5239,1513774644971,194 -5240,1513774968300,212 -5241,1513775421455,208 -5242,1513775557128,202 -5243,1513775653622,198 -5244,1513775971564,196 -5245,1513776163781,190 -5246,1513776745722,184 -5247,1513777146785,180 -5248,1513777228104,178 -5249,1513777740344,176 -5250,1513777769146,171 -5251,1513778246755,178 -5252,1513778827183,170 -5253,1513779101647,163 -5254,1513779198437,157 -5255,1513779286055,156 -5256,1513779335416,152 -5257,1513779597489,153 -5258,1513779793856,156 -5259,1513780518581,152 -5260,1513780865826,146 -5261,1513780969687,140 -5262,1513781108498,135 -5263,1513781627272,130 -5264,1513782016751,123 -5265,1513782501777,116 -5266,1513782634127,110 -5267,1513782668647,106 -5268,1513782826441,107 -5269,1513782967882,101 -5270,1513783154183,96 -5271,1513783235822,90 -5272,1513783474297,87 -5273,1513783497424,82 -5274,1513783676419,83 -5275,1513783942935,76 -5276,1513784169295,69 -5277,1513784604004,63 -5278,1513784655570,62 -5279,1513784714534,58 -5280,1513784859310,55 -5281,1513785164986,48 -5282,1513785189108,41 -5283,1513785256533,40 -5284,1513785264247,35 -5285,1513785426597,41 -5286,1513785597538,39 -5287,1513785624043,32 -5288,1513785672817,27 -5289,1513785714378,22 -5290,1513785752437,17 -5291,1513785821372,12 -5292,1513785864737,7 -5293,1513785875756,1 -5294,1513785900073,1 -5295,1513785912224,1 -5296,1513785920400,1 -5297,1513785929166,1 -5298,1513785937485,1 -5299,1513785946187,1 -5300,1513785960821,1 -5301,1513785968939,1 -5302,1513785977719,20 -5303,1513786074475,20 -5304,1513786088036,16 -5305,1513786129421,15 -5306,1513786140466,14 -5307,1513786154797,12 -5308,1513786184127,12 -5309,1513786210919,9 -5310,1513786219511,9 -5311,1513786240097,7 -5312,1513786254417,4 -5313,1513786266504,1 -5314,1513786274018,2 -5315,1513786285537,1 -5316,1513786297031,1 -5317,1513786304962,1 -5318,1513786322824,1 -5319,1513786327972,1 -5320,1513786336402,1 -5321,1513786344909,1 -5322,1513786353371,1 -5323,1513786362202,1 -5324,1513786370433,1 -5325,1513786378452,1 -5326,1513786387159,1 -5327,1513786395420,1 -5328,1513786403652,1 -5329,1513786411794,1 -5330,1513786423228,1 -5331,1513786437125,1 -5332,1513786442479,1 -5333,1513786451410,1 -5334,1513786459696,1 -5335,1513786467621,1 -5336,1513786475680,1 -5337,1513786484353,1 -5338,1513786493184,1 -5339,1513786501249,1 -5340,1513786509611,1 -5341,1513786517900,1 -5342,1513786526428,1 -5343,1513786534633,1 -5344,1513786543338,1 -5345,1513786552078,1 -5346,1513786569491,1 -5347,1513786577476,1 -5348,1513786586136,1 -5349,1513786594831,1 -5350,1513786602905,1 -5351,1513786611112,1 -5352,1513786619054,1 -5353,1513786627821,1 -5354,1513786635632,1 -5355,1513786643928,1 -5356,1513786652391,1 -5357,1513786660830,1 -5358,1513786669267,1 -5359,1513786676996,1 -5360,1513786688039,1 -5361,1513786696438,1 -5362,1513786704538,1 -5363,1513786713042,1 -5364,1513786724380,1 -5365,1513786735423,1 -5366,1513786743785,1 -5367,1513786755913,1 -5368,1513786763811,1 -5369,1513786772099,1 -5370,1513786780479,1 -5371,1513786788764,1 -5372,1513786796976,1 -5373,1513786805092,1 -5374,1513786816717,1 -5375,1513786824813,1 -5376,1513786833206,1 -5377,1513786841373,1 -5378,1513786855602,1 -5379,1513786867311,1 -5380,1513786875814,1 -5381,1513786886432,1 -5382,1513786894547,1 -5383,1513786903173,1 -5384,1513786911764,1 -5385,1513786920426,1 -5386,1513786928587,1 -5387,1513786936955,1 -5388,1513786945363,1 -5389,1513786953225,1 -5390,1513786961610,2 -5391,1513786969924,2 -5392,1513786993369,2 -5393,1513787011158,2 -5394,1513787028310,2 -5395,1513787039625,1 -5396,1513787048057,1 -5397,1513787057456,1 -5398,1513787071477,1 -5399,1513787079497,1 -5400,1513787091570,1 -5401,1513787102907,1 -5402,1513787110996,1 -5403,1513787122358,1 -5404,1513787136971,1 -5405,1513787147955,2 -5406,1513787160172,2 -5407,1513787171664,4 -5408,1513787180042,5 -5409,1513787204252,7 -5410,1513787227773,7 -5411,1513787256878,9 -5412,1513787286455,10 -5413,1513787306881,10 -5414,1513787315635,11 -5415,1513787336880,13 -5416,1513787366084,14 -5417,1513787386219,16 -5418,1513787428389,16 -5419,1513787448949,17 -5420,1513787469419,19 -5421,1513787501940,20 -5422,1513787523284,21 -5423,1513787605559,24 -5424,1513787671704,24 -5425,1513787742136,23 -5426,1513787774612,24 -5427,1513787917960,25 -5428,1513787931926,25 -5429,1513787949003,28 -5430,1513787981497,32 -5431,1513788010971,34 -5432,1513788130052,35 -5433,1513788230794,36 -5434,1513788286958,35 -5435,1513788317900,36 -5436,1513788383497,38 -5437,1513788455769,39 -5438,1513788506011,39 -5439,1513788560580,40 -5440,1513788671720,41 -5441,1513788732704,41 -5442,1513788843914,41 -5443,1513788982655,42 -5444,1513789164320,41 -5445,1513789293538,41 -5446,1513789333075,40 -5447,1513789415509,42 -5448,1513789445359,42 -5449,1513789480757,44 -5450,1513789511321,47 -5451,1513789614317,49 -5452,1513789767772,49 -5453,1513789784143,48 -5454,1513789824869,55 -5455,1513789911542,56 -5456,1513790091200,56 -5457,1513790255459,55 -5458,1513790360117,55 -5459,1513790586965,55 -5460,1513790757827,54 -5461,1513790866015,53 -5462,1513791055932,54 -5463,1513791371787,53 -5464,1513791416959,51 -5465,1513791536188,53 -5466,1513791750419,53 -5467,1513791839531,51 -5468,1513791937480,52 -5469,1513792166470,51 -5470,1513792331605,50 -5471,1513792541352,49 -5472,1513792598826,49 -5473,1513792685144,49 -5474,1513792760706,49 -5475,1513792903606,49 -5476,1513793032499,48 -5477,1513793204937,47 -5478,1513793373042,47 -5479,1513793505751,46 -5480,1513793823044,44 -5481,1513794030718,43 -5482,1513794050881,42 -5483,1513794157942,45 -5484,1513794361704,44 -5485,1513794369218,44 -5486,1513794497512,56 -5487,1513794626504,54 -5488,1513794649831,54 -5489,1513794727650,58 -5490,1513794885405,58 -5491,1513794995796,57 -5492,1513795025748,56 -5493,1513795170546,58 -5494,1513795260513,57 -5495,1513795296554,57 -5496,1513795396085,57 -5497,1513795548065,57 -5498,1513795636670,56 -5499,1513795771089,55 -5500,1513795945982,53 -5501,1513796116369,52 -5502,1513796301688,51 -5503,1513796393314,48 -5504,1513796551580,48 -5505,1513796631319,46 -5506,1513796676155,45 -5507,1513796799416,45 -5508,1513796987440,44 -5509,1513797074043,43 -5510,1513797143958,42 -5511,1513797204137,41 -5512,1513797222782,40 -5513,1513797284215,43 -5514,1513797317662,43 -5515,1513797426941,45 -5516,1513797652330,45 -5517,1513797769272,43 -5518,1513797871449,42 -5519,1513797984207,41 -5520,1513798081179,40 -5521,1513798122638,39 -5522,1513798135860,40 -5523,1513798176066,46 -5524,1513798220080,46 -5525,1513798273619,47 -5526,1513798311303,47 -5527,1513798421859,48 -5528,1513798608166,47 -5529,1513798739611,46 -5530,1513798891787,47 -5531,1513799066271,46 -5532,1513799132395,45 -5533,1513799167207,45 -5534,1513799188235,46 -5535,1513799234204,49 -5536,1513799281869,51 -5537,1513799307050,51 -5538,1513799421370,54 -5539,1513799540117,54 -5540,1513799573119,53 -5541,1513799594572,54 -5542,1513799628213,59 -5543,1513799660217,60 -5544,1513799681808,62 -5545,1513799772802,67 -5546,1513799906236,66 -5547,1513800083534,64 -5548,1513800310521,63 -5549,1513800423134,62 -5550,1513800436874,63 -5551,1513800477214,72 -5552,1513800508660,74 -5553,1513800712162,77 -5554,1513800935461,78 -5555,1513801142135,78 -5556,1513801289267,76 -5557,1513801433589,75 -5558,1513801563988,73 -5559,1513801685948,73 -5560,1513801804455,72 -5561,1513802071296,70 -5562,1513802546141,68 -5563,1513802969688,66 -5564,1513803022315,64 -5565,1513803302209,65 -5566,1513803611050,63 -5567,1513803647647,60 -5568,1513803721287,62 -5569,1513803821670,62 -5570,1513803891431,60 -5571,1513803981572,59 -5572,1513804040650,58 -5573,1513804190796,58 -5574,1513804299739,57 -5575,1513804450929,56 -5576,1513804602963,54 -5577,1513804725358,52 -5578,1513804841450,50 -5579,1513804970002,48 -5580,1513805035007,46 -5581,1513805138113,45 -5582,1513805221862,43 -5583,1513805333315,43 -5584,1513805462467,42 -5585,1513805590131,40 -5586,1513805615699,45 -5587,1513805745631,46 -5588,1513805962447,45 -5589,1513806056271,45 -5590,1513806123035,44 -5591,1513806127741,43 -5592,1513806362307,63 -5593,1513806505519,63 -5594,1513806647607,61 -5595,1513806923951,60 -5596,1513807072391,59 -5597,1513807193369,57 -5598,1513807604914,56 -5599,1513808062062,54 -5600,1513808211211,52 -5601,1513808336780,50 -5602,1513808417380,48 -5603,1513808507573,47 -5604,1513808649654,46 -5605,1513808783737,44 -5606,1513808888398,42 -5607,1513808926926,41 -5608,1513809051388,41 -5609,1513809143866,39 -5610,1513809249011,38 -5611,1513809312810,37 -5612,1513809331150,35 -5613,1513809362171,40 -5614,1513809429826,41 -5615,1513809579289,40 -5616,1513809684024,38 -5617,1513809778129,37 -5618,1513809789293,35 -5619,1513809822403,40 -5620,1513809939455,40 -5621,1513810101015,38 -5622,1513810182528,36 -5623,1513810218915,38 -5624,1513810277923,38 -5625,1513810350705,38 -5626,1513810398983,37 -5627,1513810413512,38 -5628,1513810499827,41 -5629,1513810592054,40 -5630,1513810634599,39 -5631,1513810669556,38 -5632,1513810783566,37 -5633,1513810838065,37 -5634,1513810848259,36 -5635,1513810929479,44 -5636,1513811014303,43 -5637,1513811038012,43 -5638,1513811117474,47 -5639,1513811200685,46 -5640,1513811261995,45 -5641,1513811445887,45 -5642,1513811695073,45 -5643,1513811815446,45 -5644,1513811855105,45 -5645,1513811879354,48 -5646,1513811908773,51 -5647,1513811945445,53 -5648,1513811966543,54 -5649,1513812026955,57 -5650,1513812118343,57 -5651,1513812183127,62 -5652,1513812426940,63 -5653,1513812482293,63 -5654,1513812577256,64 -5655,1513812731024,63 -5656,1513812849110,62 -5657,1513812925717,60 -5658,1513813185877,60 -5659,1513813383936,58 -5660,1513813405934,57 -5661,1513813601472,62 -5662,1513813652838,60 -5663,1513813740248,59 -5664,1513813867572,59 -5665,1513813967828,58 -5666,1513814069154,57 -5667,1513814172895,55 -5668,1513814198215,55 -5669,1513814219132,59 -5670,1513814351557,63 -5671,1513814553651,62 -5672,1513814682774,61 -5673,1513814877664,60 -5674,1513815261643,58 -5675,1513815272192,56 -5676,1513815373842,67 -5677,1513815618108,66 -5678,1513815871931,64 -5679,1513815974134,61 -5680,1513816078970,60 -5681,1513816210315,59 -5682,1513816441786,57 -5683,1513816629876,55 -5684,1513816731079,53 -5685,1513816815375,52 -5686,1513816842962,50 -5687,1513816874719,53 -5688,1513816914483,55 -5689,1513816984157,55 -5690,1513817039499,55 -5691,1513817101910,54 -5692,1513817261800,64 -5693,1513817462705,63 -5694,1513817504294,61 -5695,1513817628566,61 -5696,1513817723877,60 -5697,1513817816403,59 -5698,1513817873108,58 -5699,1513817934428,57 -5700,1513817980296,57 -5701,1513818136111,57 -5702,1513818202257,56 -5703,1513818216596,55 -5704,1513818398119,62 -5705,1513818679517,59 -5706,1513818866099,57 -5707,1513819049726,55 -5708,1513819591099,54 -5709,1513819651732,51 -5710,1513819842330,50 -5711,1513820005911,48 -5712,1513820048441,46 -5713,1513820180330,47 -5714,1513820385380,47 -5715,1513820576191,45 -5716,1513820698792,42 -5717,1513820848112,41 -5718,1513820892454,39 -5719,1513820976630,42 -5720,1513821061215,41 -5721,1513821116379,40 -5722,1513821131476,38 -5723,1513821205794,42 -5724,1513821295283,41 -5725,1513821353264,40 -5726,1513821423821,40 -5727,1513821481672,39 -5728,1513821527658,40 -5729,1513821615552,40 -5730,1513821773054,38 -5731,1513821856787,37 -5732,1513821936246,36 -5733,1513822067855,34 -5734,1513822089020,33 -5735,1513822214938,38 -5736,1513822336680,36 -5737,1513822393114,35 -5738,1513822496662,35 -5739,1513822571307,34 -5740,1513822625978,33 -5741,1513822834154,33 -5742,1513823050261,31 -5743,1513823369038,28 -5744,1513823434304,26 -5745,1513823541652,26 -5746,1513823640278,25 -5747,1513823660762,26 -5748,1513823698641,27 -5749,1513823788229,30 -5750,1513823945938,29 -5751,1513823965646,28 -5752,1513823989704,29 -5753,1513823998309,31 -5754,1513824065859,38 -5755,1513824120835,37 -5756,1513824187778,37 -5757,1513824405875,35 -5758,1513824713748,34 -5759,1513824743740,32 -5760,1513824814832,32 -5761,1513824866727,33 -5762,1513824893458,33 -5763,1513825068133,34 -5764,1513825109820,33 -5765,1513825261078,33 -5766,1513825327835,31 -5767,1513825420281,30 -5768,1513825499467,29 -5769,1513825564696,30 -5770,1513825606567,32 -5771,1513825642291,32 -5772,1513825801760,32 -5773,1513825851091,30 -5774,1513825859124,30 -5775,1513825880638,37 -5776,1513825930764,44 -5777,1513825997222,45 -5778,1513826001947,44 -5779,1513826019804,64 -5780,1513826043986,71 -5781,1513826112681,76 -5782,1513826282233,76 -5783,1513826287102,74 -5784,1513826300205,108 -5785,1513826455060,124 -5786,1513826667456,123 -5787,1513826699993,123 -5788,1513826749006,130 -5789,1513826770682,133 -5790,1513827199758,145 -5791,1513827341761,143 -5792,1513827729945,143 -5793,1513828418238,139 -5794,1513828738200,137 -5795,1513828866287,135 -5796,1513828888717,135 -5797,1513829109489,145 -5798,1513829568739,143 -5799,1513829892223,141 -5800,1513829950125,138 -5801,1513830815841,141 -5802,1513831609955,138 -5803,1513832030932,134 -5804,1513832664603,136 -5805,1513832862688,133 -5806,1513832906000,131 -5807,1513833001167,134 -5808,1513833111209,133 -5809,1513833180618,132 -5810,1513833329994,133 -5811,1513833503741,131 -5812,1513833851921,129 -5813,1513834455807,126 -5814,1513834804343,123 -5815,1513835195392,120 -5816,1513835941745,116 -5817,1513836409011,113 -5818,1513836526504,108 -5819,1513836651782,108 -5820,1513836893887,106 -5821,1513837270517,103 -5822,1513838441498,100 -5823,1513839798234,99 -5824,1513840897309,95 -5825,1513841838608,92 -5826,1513841980773,89 -5827,1513842111355,87 -5828,1513842227202,84 -5829,1513842328679,83 -5830,1513842441661,81 -5831,1513842679316,79 -5832,1513842847786,76 -5833,1513842880108,73 -5834,1513843024948,74 -5835,1513843265623,74 -5836,1513843432989,70 -5837,1513843501005,67 -5838,1513843666267,66 -5839,1513843960776,62 -5840,1513844004570,60 -5841,1513844137236,59 -5842,1513844541335,56 -5843,1513844874840,52 -5844,1513844944620,48 -5845,1513845062389,46 -5846,1513845197622,42 -5847,1513845322245,39 -5848,1513845469970,37 -5849,1513845566414,34 -5850,1513845590922,31 -5851,1513845612737,30 -5852,1513845624471,30 -5853,1513845639256,34 -5854,1513845769164,39 -5855,1513845910957,35 -5856,1513845938025,33 -5857,1513846030540,32 -5858,1513846232691,28 -5859,1513846258270,24 -5860,1513846310346,24 -5861,1513846345092,20 -5862,1513846374983,18 -5863,1513846417509,18 -5864,1513846443721,14 -5865,1513846482844,12 -5866,1513846513956,9 -5867,1513846552949,6 -5868,1513846571105,2 -5869,1513846582862,1 -5870,1513846590994,1 -5871,1513846603385,1 -5872,1513846615370,1 -5873,1513846624514,1 -5874,1513846633285,1 -5875,1513846641025,1 -5876,1513846645633,1 -5877,1513846653722,1 -5878,1513846662469,1 -5879,1513846671655,1 -5880,1513846683250,1 -5881,1513846695169,1 -5882,1513846707983,1 -5883,1513846716836,1 -5884,1513846728632,1 -5885,1513846740325,1 -5886,1513846749120,1 -5887,1513846758205,1 -5888,1513846769584,1 -5889,1513846774139,2 -5890,1513846786921,8 -5891,1513846805483,7 -5892,1513846814930,8 -5893,1513846826721,8 -5894,1513846838622,8 -5895,1513846852716,8 -5896,1513846903062,9 -5897,1513846907258,14 -5898,1513846929878,21 -5899,1513846993831,21 -5900,1513847039066,20 -5901,1513847060469,23 -5902,1513847081108,24 -5903,1513847098636,24 -5904,1513847131441,26 -5905,1513847248681,26 -5906,1513847324805,25 -5907,1513847410344,28 -5908,1513847439512,28 -5909,1513847848009,30 -5910,1513848319391,30 -5911,1513848399147,30 -5912,1513848434585,29 -5913,1513848454157,31 -5914,1513848492608,33 -5915,1513848518235,34 -5916,1513848672297,35 -5917,1513848890036,34 -5918,1513848996644,33 -5919,1513849053689,32 -5920,1513849105383,33 -5921,1513849133097,33 -5922,1513849161450,34 -5923,1513849300151,36 -5924,1513849501381,34 -5925,1513849668759,33 -5926,1513849763987,31 -5927,1513849788674,30 -5928,1513849804445,33 -5929,1513849851571,37 -5930,1513849955670,37 -5931,1513850091400,36 -5932,1513850157513,36 -5933,1513850214541,36 -5934,1513850267548,37 -5935,1513850276040,37 -5936,1513850400872,47 -5937,1513850431563,46 -5938,1513850816413,49 -5939,1513851046334,47 -5940,1513851097075,46 -5941,1513851118131,47 -5942,1513851142342,51 -5943,1513851191168,55 -5944,1513851311191,55 -5945,1513851558735,55 -5946,1513851816005,53 -5947,1513852250670,52 -5948,1513852260970,51 -5949,1513852342395,61 -5950,1513852430246,60 -5951,1513852563412,60 -5952,1513852793339,60 -5953,1513852947084,62 -5954,1513853006797,64 -5955,1513853072589,64 -5956,1513853162347,64 -5957,1513853209611,66 -5958,1513853367207,67 -5959,1513853511200,65 -5960,1513853640274,66 -5961,1513853778365,65 -5962,1513853816715,65 -5963,1513854032446,67 -5964,1513854299525,65 -5965,1513854427277,65 -5966,1513854630083,64 -5967,1513854859429,62 -5968,1513854915621,61 -5969,1513855512853,62 -5970,1513855556674,60 -5971,1513855821893,61 -5972,1513855851220,58 -5973,1513855926780,61 -5974,1513856060430,61 -5975,1513856166492,59 -5976,1513856233029,58 -5977,1513856555882,58 -5978,1513856753236,56 -5979,1513856824859,54 -5980,1513856854296,53 -5981,1513857021785,55 -5982,1513857067244,53 -5983,1513857216208,53 -5984,1513857265043,52 -5985,1513857342422,52 -5986,1513857479452,50 -5987,1513857490419,49 -5988,1513857580733,57 -5989,1513857658635,55 -5990,1513857800299,54 -5991,1513857844643,53 -5992,1513857873401,54 -5993,1513858030273,56 -5994,1513858121106,55 -5995,1513858323049,54 -5996,1513858367300,52 -5997,1513858498150,52 -5998,1513858943620,55 -5999,1513859436897,53 -6000,1513859530197,50 -6001,1513859580821,49 -6002,1513859654454,51 -6003,1513859716136,50 -6004,1513859774511,50 -6005,1513859835095,51 -6006,1513859912672,51 -6007,1513859939444,49 -6008,1513860037887,52 -6009,1513860155074,51 -6010,1513860291470,49 -6011,1513860339275,47 -6012,1513860420664,46 -6013,1513860718807,46 -6014,1513860827050,45 -6015,1513860925397,44 -6016,1513861024812,44 -6017,1513861142560,42 -6018,1513861180616,41 -6019,1513861230994,40 -6020,1513861375503,41 -6021,1513861482544,39 -6022,1513861514097,38 -6023,1513861610927,40 -6024,1513861636251,38 -6025,1513861643705,39 -6026,1513861684237,49 -6027,1513861817687,49 -6028,1513861933539,48 -6029,1513862045220,48 -6030,1513862171087,48 -6031,1513862464747,46 -6032,1513862707097,43 -6033,1513862717413,42 -6034,1513862764606,49 -6035,1513862881737,49 -6036,1513863106045,52 -6037,1513863125474,50 -6038,1513863235653,55 -6039,1513863302584,53 -6040,1513863408826,52 -6041,1513863485183,50 -6042,1513863513296,53 -6043,1513863584975,57 -6044,1513863830513,56 -6045,1513863904146,54 -6046,1513864032698,53 -6047,1513864107996,52 -6048,1513864122591,50 -6049,1513864199640,62 -6050,1513864268469,62 -6051,1513864302357,62 -6052,1513864385954,64 -6053,1513864501079,63 -6054,1513864529599,62 -6055,1513864573277,65 -6056,1513864650595,66 -6057,1513864709336,66 -6058,1513864774355,67 -6059,1513864873102,68 -6060,1513865026779,66 -6061,1513865345056,65 -6062,1513865416696,63 -6063,1513865436173,64 -6064,1513865499754,68 -6065,1513865566595,69 -6066,1513865611443,69 -6067,1513865659588,69 -6068,1513865675835,69 -6069,1513865799483,78 -6070,1513865933154,75 -6071,1513866083024,76 -6072,1513866194318,73 -6073,1513866259515,74 -6074,1513866316684,74 -6075,1513866543349,74 -6076,1513866596997,72 -6077,1513866742527,73 -6078,1513866879031,71 -6079,1513866900088,69 -6080,1513866918395,74 -6081,1513866972998,82 -6082,1513867357316,83 -6083,1513867392873,81 -6084,1513867508336,83 -6085,1513867668973,83 -6086,1513867743944,81 -6087,1513867795475,80 -6088,1513867923674,85 -6089,1513867971360,84 -6090,1513868049951,86 -6091,1513868308818,85 -6092,1513868323318,83 -6093,1513868592320,96 -6094,1513868743628,93 -6095,1513869098850,91 -6096,1513869133009,89 -6097,1513869346269,93 -6098,1513869451279,90 -6099,1513869586924,89 -6100,1513870131068,86 -6101,1513870135412,83 -6102,1513870231830,127 -6103,1513870389941,126 -6104,1513870571873,124 -6105,1513870802565,122 -6106,1513870835304,120 -6107,1513871012779,125 -6108,1513871320786,123 -6109,1513871361598,121 -6110,1513871555281,124 -6111,1513871571456,120 -6112,1513871911057,136 -6113,1513871952092,132 -6114,1513872006355,135 -6115,1513872072855,136 -6116,1513872285130,136 -6117,1513872447282,133 -6118,1513872683845,131 -6119,1513872791603,127 -6120,1513873171047,126 -6121,1513873742575,122 -6122,1513873905863,118 -6123,1513874069753,116 -6124,1513874493823,113 -6125,1513874667793,110 -6126,1513874970266,112 -6127,1513875065121,110 -6128,1513875118290,108 -6129,1513875473492,109 -6130,1513875597958,105 -6131,1513875671934,102 -6132,1513875872973,101 -6133,1513876094087,96 -6134,1513876140986,98 -6135,1513876191976,99 -6136,1513876368773,99 -6137,1513876909552,95 -6138,1513877451744,94 -6139,1513877791837,89 -6140,1513878064607,86 -6141,1513878105652,82 -6142,1513878134207,84 -6143,1513878265115,88 -6144,1513878302564,85 -6145,1513878386481,84 -6146,1513878516602,84 -6147,1513878639935,80 -6148,1513878929617,78 -6149,1513879074254,77 -6150,1513879505356,75 -6151,1513879699289,71 -6152,1513879706350,69 -6153,1513879843496,89 -6154,1513880050270,85 -6155,1513880377357,84 -6156,1513880497800,81 -6157,1513880851680,79 -6158,1513880921640,75 -6159,1513880953042,73 -6160,1513881037412,76 -6161,1513881165656,73 -6162,1513881247046,69 -6163,1513881317224,67 -6164,1513881352372,68 -6165,1513881359708,68 -6166,1513881429128,87 -6167,1513881545691,86 -6168,1513881890966,84 -6169,1513881975517,85 -6170,1513881979882,83 -6171,1513882135683,123 -6172,1513882244138,120 -6173,1513882468356,117 -6174,1513882883064,114 -6175,1513882950095,110 -6176,1513883430135,109 -6177,1513883535599,105 -6178,1513883579010,102 -6179,1513883704944,103 -6180,1513883826983,102 -6181,1513883921779,103 -6182,1513884077895,101 -6183,1513884179195,97 -6184,1513884331873,97 -6185,1513884417540,93 -6186,1513884635958,91 -6187,1513884982919,87 -6188,1513885256172,84 -6189,1513885309475,80 -6190,1513885440249,80 -6191,1513885621927,77 -6192,1513885701337,73 -6193,1513885784441,76 -6194,1513886268336,74 -6195,1513886532235,69 -6196,1513886666351,64 -6197,1513886824284,63 -6198,1513887185097,59 -6199,1513887367079,55 -6200,1513887397310,51 -6201,1513887458217,50 -6202,1513887519037,70 -6203,1513887574169,69 -6204,1513887653171,69 -6205,1513887727095,66 -6206,1513888042496,65 -6207,1513888063588,65 -6208,1513888202248,68 -6209,1513888206606,65 -6210,1513888217064,100 -6211,1513888364755,119 -6212,1513888448031,124 -6213,1513888689821,123 -6214,1513888724169,122 -6215,1513888786419,129 -6216,1513889433693,131 -6217,1513889451344,127 -6218,1513889605494,140 -6219,1513889989168,138 -6220,1513890009785,133 -6221,1513890429268,144 -6222,1513890695707,140 -6223,1513890918921,136 -6224,1513890975534,133 -6225,1513891125908,133 -6226,1513891332068,130 -6227,1513891405931,126 -6228,1513891595425,126 -6229,1513891730374,123 -6230,1513892051931,120 -6231,1513892312943,116 -6232,1513892753058,113 -6233,1513892999442,109 -6234,1513893074049,105 -6235,1513893274044,105 -6236,1513893366491,103 -6237,1513893441551,100 -6238,1513893872477,98 -6239,1513893892965,94 -6240,1513893933904,99 -6241,1513894182701,98 -6242,1513894243291,97 -6243,1513894368274,98 -6244,1513894439298,95 -6245,1513894586528,96 -6246,1513894699356,92 -6247,1513894738600,89 -6248,1513894936361,90 -6249,1513895135965,85 -6250,1513895301390,81 -6251,1513895735316,76 -6252,1513895739919,71 -6253,1513895786345,115 -6254,1513895871259,115 -6255,1513896272847,112 -6256,1513896304591,108 -6257,1513896402660,110 -6258,1513896512194,106 -6259,1513896884636,104 -6260,1513897033652,101 -6261,1513897272523,97 -6262,1513897420310,93 -6263,1513897434219,89 -6264,1513897463930,100 -6265,1513897563531,103 -6266,1513897847834,111 -6267,1513897993013,107 -6268,1513898261072,104 -6269,1513898414209,99 -6270,1513898714053,95 -6271,1513898860958,114 -6272,1513898914953,111 -6273,1513899089816,112 -6274,1513899175933,108 -6275,1513899596183,106 -6276,1513899753299,103 -6277,1513899844980,99 -6278,1513899912586,98 -6279,1513900098097,99 -6280,1513900223350,95 -6281,1513900475295,93 -6282,1513900659817,90 -6283,1513900747577,87 -6284,1513900831888,84 -6285,1513901100517,82 -6286,1513901147367,79 -6287,1513901306150,78 -6288,1513901499924,74 -6289,1513901690190,69 -6290,1513901805961,67 -6291,1513901840656,64 -6292,1513901980335,63 -6293,1513902124330,60 -6294,1513902227993,57 -6295,1513902284099,52 -6296,1513902347335,49 -6297,1513902391101,46 -6298,1513902482858,44 -6299,1513902518081,40 -6300,1513902544002,37 -6301,1513902608088,37 -6302,1513902657388,34 -6303,1513902675013,31 -6304,1513902723855,31 -6305,1513902758356,29 -6306,1513902769406,27 -6307,1513902868791,26 -6308,1513902918011,26 -6309,1513902922383,22 -6310,1513902958573,47 -6311,1513903019000,57 -6312,1513903091747,55 -6313,1513903184241,54 -6314,1513903294858,50 -6315,1513903336586,52 -6316,1513903359770,52 -6317,1513903407295,53 -6318,1513903558820,60 -6319,1513903602993,58 -6320,1513903693301,57 -6321,1513903936685,61 -6322,1513904170285,58 -6323,1513904286322,55 -6324,1513904496593,52 -6325,1513904694509,52 -6326,1513904894555,49 -6327,1513905259430,46 -6328,1513905359332,45 -6329,1513905406603,42 -6330,1513905534329,41 -6331,1513905707964,38 -6332,1513905944517,35 -6333,1513906141720,32 -6334,1513906161650,28 -6335,1513906203514,29 -6336,1513906245774,27 -6337,1513906278746,27 -6338,1513906308657,25 -6339,1513906359532,24 -6340,1513906363578,27 -6341,1513906384086,42 -6342,1513906483785,43 -6343,1513906623645,41 -6344,1513906760452,40 -6345,1513906866571,38 -6346,1513906984229,35 -6347,1513907018852,32 -6348,1513907088521,33 -6349,1513907163284,31 -6350,1513907242032,28 -6351,1513907388121,25 -6352,1513907500848,23 -6353,1513907507983,38 -6354,1513907562353,50 -6355,1513907741809,51 -6356,1513907917589,49 -6357,1513907990436,50 -6358,1513908050883,49 -6359,1513908113198,49 -6360,1513908194091,48 -6361,1513908317620,46 -6362,1513908514057,44 -6363,1513908631872,43 -6364,1513908675656,48 -6365,1513908710198,50 -6366,1513908745839,53 -6367,1513908989211,54 -6368,1513909239582,51 -6369,1513909303367,50 -6370,1513909338996,49 -6371,1513909352692,50 -6372,1513909385706,56 -6373,1513909427722,60 -6374,1513909723311,61 -6375,1513910018025,59 -6376,1513910040485,57 -6377,1513910156333,61 -6378,1513910349940,60 -6379,1513910480469,59 -6380,1513910586660,57 -6381,1513910696336,56 -6382,1513910730947,55 -6383,1513910735185,56 -6384,1513910745700,86 -6385,1513910765618,103 -6386,1513910960054,112 -6387,1513911484427,111 -6388,1513911534970,107 -6389,1513911647981,109 -6390,1513911796244,107 -6391,1513911817457,105 -6392,1513911850863,116 -6393,1513911882678,120 -6394,1513911984159,125 -6395,1513912335671,124 -6396,1513912568881,121 -6397,1513912963971,119 -6398,1513913577204,117 -6399,1513913581605,114 -6400,1513913870430,172 -6401,1513914032554,170 -6402,1513914144230,167 -6403,1513914407114,167 -6404,1513914654534,165 -6405,1513915036675,163 -6406,1513915509087,159 -6407,1513915578723,157 -6408,1513915922147,158 -6409,1513916109250,153 -6410,1513916410523,157 -6411,1513916729864,155 -6412,1513916808813,151 -6413,1513917031356,151 -6414,1513917503205,149 -6415,1513917656636,145 -6416,1513917944402,143 -6417,1513917994211,142 -6418,1513918135472,145 -6419,1513918203703,143 -6420,1513918293971,144 -6421,1513918510488,143 -6422,1513919131405,140 -6423,1513919673244,135 -6424,1513920104978,132 -6425,1513920128817,127 -6426,1513920142977,135 -6427,1513920315844,153 -6428,1513920353188,150 -6429,1513920493734,154 -6430,1513921327947,151 -6431,1513921448193,147 -6432,1513921574410,143 -6433,1513921802418,140 -6434,1513921855993,136 -6435,1513922048298,138 -6436,1513922098618,134 -6437,1513922373614,135 -6438,1513922435217,131 -6439,1513922689009,131 -6440,1513922873857,126 -6441,1513923091670,130 -6442,1513923141172,128 -6443,1513923221344,129 -6444,1513923360276,127 -6445,1513923816004,123 -6446,1513924176902,119 -6447,1513924429553,113 -6448,1513924746665,110 -6449,1513924767869,105 -6450,1513925217647,111 -6451,1513925335944,106 -6452,1513925370090,102 -6453,1513925517066,103 -6454,1513925609355,105 -6455,1513925844242,101 -6456,1513926007262,98 -6457,1513926225612,93 -6458,1513926330658,89 -6459,1513926706483,86 -6460,1513926751548,81 -6461,1513926837115,80 -6462,1513926937395,76 -6463,1513927075953,72 -6464,1513927132178,67 -6465,1513927579648,65 -6466,1513927599119,61 -6467,1513927823171,64 -6468,1513927828040,59 -6469,1513928088379,81 -6470,1513928166120,77 -6471,1513928357689,74 -6472,1513928469195,72 -6473,1513928767325,69 -6474,1513928984083,65 -6475,1513929051532,60 -6476,1513929134650,56 -6477,1513929533960,54 -6478,1513929555377,48 -6479,1513929621877,48 -6480,1513929675377,44 -6481,1513929763663,39 -6482,1513929786485,35 -6483,1513929885952,34 -6484,1513929943474,45 -6485,1513929990546,50 -6486,1513930027998,53 -6487,1513930157313,52 -6488,1513930207545,48 -6489,1513930233159,47 -6490,1513930312964,46 -6491,1513930340873,44 -6492,1513930372099,47 -6493,1513930573383,50 -6494,1513930607834,49 -6495,1513930649288,49 -6496,1513930732538,47 -6497,1513930773190,43 -6498,1513930853854,41 -6499,1513931012640,37 -6500,1513931019886,64 -6501,1513931178383,81 -6502,1513931248308,78 -6503,1513931467265,78 -6504,1513931569019,76 -6505,1513931739826,73 -6506,1513932205557,70 -6507,1513932295246,66 -6508,1513932320859,66 -6509,1513932432467,68 -6510,1513932489238,66 -6511,1513932642650,65 -6512,1513932785351,62 -6513,1513933096619,60 -6514,1513933126260,57 -6515,1513933177100,57 -6516,1513933329693,56 -6517,1513933453876,53 -6518,1513933479857,52 -6519,1513933628548,54 -6520,1513933660015,53 -6521,1513933730402,54 -6522,1513933866081,52 -6523,1513933907066,49 -6524,1513933970021,47 -6525,1513934096729,44 -6526,1513934191510,47 -6527,1513934259368,56 -6528,1513934336113,54 -6529,1513934404745,56 -6530,1513934598797,55 -6531,1513934758020,53 -6532,1513934859890,50 -6533,1513934898005,49 -6534,1513934940818,49 -6535,1513934951782,51 -6536,1513934998539,59 -6537,1513935100044,61 -6538,1513935186321,59 -6539,1513935740867,60 -6540,1513935893549,56 -6541,1513936079707,53 -6542,1513936275272,52 -6543,1513936302155,51 -6544,1513936335888,54 -6545,1513936360008,55 -6546,1513936413780,57 -6547,1513936448675,56 -6548,1513936489792,56 -6549,1513936518320,55 -6550,1513936660470,62 -6551,1513936725805,59 -6552,1513936769580,58 -6553,1513936913080,61 -6554,1513937015181,59 -6555,1513937272968,58 -6556,1513937513235,55 -6557,1513937559785,52 -6558,1513937645487,52 -6559,1513937714492,50 -6560,1513938104957,49 -6561,1513938439516,47 -6562,1513938487446,45 -6563,1513938622838,44 -6564,1513938768988,41 -6565,1513938773351,40 -6566,1513938808918,58 -6567,1513938833092,62 -6568,1513939050065,64 -6569,1513939182075,75 -6570,1513939342797,74 -6571,1513939420001,72 -6572,1513939760844,71 -6573,1513939810868,68 -6574,1513939863612,67 -6575,1513940074739,67 -6576,1513940490692,65 -6577,1513940511488,62 -6578,1513940582620,67 -6579,1513940647370,68 -6580,1513940781994,67 -6581,1513940995015,65 -6582,1513941251984,63 -6583,1513941528167,61 -6584,1513941555599,58 -6585,1513941595190,61 -6586,1513941935030,61 -6587,1513942335613,60 -6588,1513942352861,57 -6589,1513942407200,63 -6590,1513942496407,63 -6591,1513942546024,62 -6592,1513942832026,63 -6593,1513942862112,62 -6594,1513943032783,63 -6595,1513943395420,62 -6596,1513943704466,60 -6597,1513943764935,57 -6598,1513944066384,57 -6599,1513944588284,54 -6600,1513944602035,51 -6601,1513944678423,67 -6602,1513944832357,66 -6603,1513944912021,65 -6604,1513945070378,64 -6605,1513945340491,62 -6606,1513945381167,59 -6607,1513945465768,59 -6608,1513945537362,58 -6609,1513945604163,60 -6610,1513945615223,59 -6611,1513945630063,70 -6612,1513945758747,78 -6613,1513946331349,76 -6614,1513946865926,73 -6615,1513946896796,72 -6616,1513947015704,75 -6617,1513947437052,73 -6618,1513947464861,70 -6619,1513947525347,75 -6620,1513947532877,74 -6621,1513947610110,96 -6622,1513947857845,95 -6623,1513948154998,92 -6624,1513948240431,91 -6625,1513948449888,90 -6626,1513949117529,88 -6627,1513950025865,85 -6628,1513951198562,81 -6629,1513951219136,78 -6630,1513951262682,84 -6631,1513951309372,85 -6632,1513951380500,86 -6633,1513951549060,84 -6634,1513951715979,82 -6635,1513951807936,81 -6636,1513951812826,84 -6637,1513951938208,123 -6638,1513952457610,122 -6639,1513952465073,118 -6640,1513952516352,151 -6641,1513952678683,154 -6642,1513952768076,150 -6643,1513953466935,149 -6644,1513954222635,147 -6645,1513954376631,144 -6646,1513954661562,143 -6647,1513955421122,140 -6648,1513955846315,138 -6649,1513956010342,135 -6650,1513956180549,134 -6651,1513956935594,132 -6652,1513957818146,128 -6653,1513958034111,124 -6654,1513958062290,121 -6655,1513958100027,127 -6656,1513958388840,130 -6657,1513958543808,126 -6658,1513958613527,124 -6659,1513958904755,123 -6660,1513959318333,119 -6661,1513959576091,115 -6662,1513960054372,111 -6663,1513960217621,107 -6664,1513960280837,104 -6665,1513960388751,102 -6666,1513960518033,111 -6667,1513960818984,109 -6668,1513961067278,109 -6669,1513961534666,105 -6670,1513962179211,101 -6671,1513962332568,97 -6672,1513962385780,94 -6673,1513962694646,94 -6674,1513963022758,91 -6675,1513963290307,88 -6676,1513963337727,84 -6677,1513963392867,83 -6678,1513963548696,86 -6679,1513963943441,83 -6680,1513964070910,80 -6681,1513964252740,78 -6682,1513964409305,73 -6683,1513964417317,70 -6684,1513964710279,86 -6685,1513965017122,85 -6686,1513965158318,81 -6687,1513965166105,78 -6688,1513965615621,97 -6689,1513965619834,96 -6690,1513965643975,147 -6691,1513966084891,156 -6692,1513966403558,152 -6693,1513966825431,147 -6694,1513967439865,144 -6695,1513967575065,139 -6696,1513967673979,135 -6697,1513967851618,132 -6698,1513967998423,128 -6699,1513968277898,125 -6700,1513968644937,119 -6701,1513969092451,118 -6702,1513969158950,113 -6703,1513969528115,111 -6704,1513969666485,107 -6705,1513969996140,102 -6706,1513970737894,97 -6707,1513971095156,94 -6708,1513971508931,88 -6709,1513971566940,84 -6710,1513971607105,82 -6711,1513971725351,87 -6712,1513971801731,89 -6713,1513971963208,86 -6714,1513972129707,82 -6715,1513972205905,77 -6716,1513972220486,76 -6717,1513972544518,83 -6718,1513973131412,77 -6719,1513973482900,75 -6720,1513973523234,71 -6721,1513973705154,81 -6722,1513973761793,78 -6723,1513973766229,76 -6724,1513973790152,111 -6725,1513973886944,118 -6726,1513973907319,114 -6727,1513973967205,122 -6728,1513974942363,120 -6729,1513975925270,114 -6730,1513976108926,111 -6731,1513976148980,109 -6732,1513976355814,111 -6733,1513976437624,106 -6734,1513976988915,104 -6735,1513977091937,98 -6736,1513977248217,95 -6737,1513977518352,111 -6738,1513977791509,107 -6739,1513978085228,102 -6740,1513978116890,117 -6741,1513978189524,124 -6742,1513978376641,123 -6743,1513979097642,122 -6744,1513979934687,117 -6745,1513980190019,111 -6746,1513980214447,108 -6747,1513980339199,114 -6748,1513980469736,111 -6749,1513980979961,108 -6750,1513981288998,103 -6751,1513981345607,99 -6752,1513981399078,99 -6753,1513981615354,97 -6754,1513981851615,93 -6755,1513982225246,94 -6756,1513982392115,92 -6757,1513982558417,89 -6758,1513982617366,86 -6759,1513982846415,86 -6760,1513982861770,82 -6761,1513983119560,89 -6762,1513983511586,85 -6763,1513983516096,81 -6764,1513983595414,119 -6765,1513983603418,118 -6766,1513983656598,149 -6767,1513983773162,150 -6768,1513984147813,146 -6769,1513984239835,141 -6770,1513984426929,137 -6771,1513984473858,133 -6772,1513984625500,133 -6773,1513984810163,130 -6774,1513985297769,126 -6775,1513985909514,119 -6776,1513986673744,113 -6777,1513986694680,109 -6778,1513987005313,116 -6779,1513987129437,111 -6780,1513987263922,106 -6781,1513987281934,102 -6782,1513987313296,109 -6783,1513987622002,110 -6784,1513987719245,115 -6785,1513987775764,111 -6786,1513988020311,109 -6787,1513988117432,103 -6788,1513988285786,110 -6789,1513988475178,105 -6790,1513988768435,128 -6791,1513988993603,130 -6792,1513989040397,127 -6793,1513989090743,127 -6794,1513990107245,129 -6795,1513991298934,122 -6796,1513991649350,118 -6797,1513991974500,115 -6798,1513992180144,111 -6799,1513992741136,107 -6800,1513993141535,102 -6801,1513993321766,98 -6802,1513993887302,93 -6803,1513994080739,90 -6804,1513994350857,85 -6805,1513994806879,81 -6806,1513994827395,76 -6807,1513994855204,78 -6808,1513994999979,80 -6809,1513995118963,75 -6810,1513995316741,72 -6811,1513995366396,69 -6812,1513995492182,68 -6813,1513995628639,65 -6814,1513995691557,60 -6815,1513995794937,57 -6816,1513995818207,54 -6817,1513995848946,59 -6818,1513996021405,59 -6819,1513996247413,54 -6820,1513996294143,49 -6821,1513996467855,48 -6822,1513996833709,42 -6823,1513996876363,38 -6824,1513996955889,57 -6825,1513997103708,58 -6826,1513997124631,55 -6827,1513997270199,63 -6828,1513997479830,62 -6829,1513997794225,58 -6830,1513998198351,53 -6831,1513998569576,50 -6832,1513998580601,48 -6833,1513998611908,54 -6834,1513998713339,56 -6835,1513999022079,52 -6836,1513999334738,49 -6837,1513999342450,44 -6838,1513999524881,53 -6839,1513999711682,49 -6840,1513999781200,45 -6841,1514000130779,46 -6842,1514000138315,44 -6843,1514000205212,54 -6844,1514000273288,51 -6845,1514000515281,47 -6846,1514000863059,43 -6847,1514000912425,43 -6848,1514001018423,42 -6849,1514001204941,38 -6850,1514001297443,34 -6851,1514001379380,31 -6852,1514001482085,29 -6853,1514001538860,26 -6854,1514001598707,23 -6855,1514001609848,19 -6856,1514001617566,19 -6857,1514001645714,21 -6858,1514001670018,18 -6859,1514001708107,16 -6860,1514001722350,12 -6861,1514001754549,17 -6862,1514001781631,13 -6863,1514001815146,10 -6864,1514001838766,28 -6865,1514001843190,28 -6866,1514001986649,57 -6867,1514002014190,57 -6868,1514002024865,60 -6869,1514002199363,70 -6870,1514002444128,69 -6871,1514002567926,67 -6872,1514002769271,67 -6873,1514003110511,66 -6874,1514003460467,63 -6875,1514003484406,59 -6876,1514003798051,62 -6877,1514003949664,58 -6878,1514004128354,62 -6879,1514004163039,59 -6880,1514004235167,61 -6881,1514004298316,60 -6882,1514004383901,65 -6883,1514004502335,67 -6884,1514004613583,66 -6885,1514004827726,65 -6886,1514004919915,65 -6887,1514004936907,64 -6888,1514005224805,70 -6889,1514005268147,68 -6890,1514005316710,69 -6891,1514005369220,69 -6892,1514005415784,70 -6893,1514005527237,72 -6894,1514005568085,74 -6895,1514005635422,74 -6896,1514005773463,74 -6897,1514005826608,72 -6898,1514005959945,71 -6899,1514006055259,70 -6900,1514006153915,69 -6901,1514006273183,67 -6902,1514006310147,65 -6903,1514006323964,65 -6904,1514006408744,74 -6905,1514006445991,72 -6906,1514006473006,73 -6907,1514006555148,80 -6908,1514006670325,82 -6909,1514006715072,80 -6910,1514006782277,81 -6911,1514007127505,81 -6912,1514007459533,79 -6913,1514007575442,76 -6914,1514007783288,74 -6915,1514007973168,72 -6916,1514008081357,70 -6917,1514008221786,70 -6918,1514008418023,70 -6919,1514008483174,67 -6920,1514008616765,67 -6921,1514008640537,65 -6922,1514008675054,68 -6923,1514008761062,69 -6924,1514008883375,68 -6925,1514009210425,66 -6926,1514009568710,63 -6927,1514009659795,62 -6928,1514009686954,62 -6929,1514009691489,63 -6930,1514010021437,93 -6931,1514010366383,89 -6932,1514010488725,86 -6933,1514010505988,88 -6934,1514010516535,98 -6935,1514010527130,116 -6936,1514011296285,138 -6937,1514012565678,134 -6938,1514013485457,135 -6939,1514014060470,131 -6940,1514014852526,127 -6941,1514015096658,124 -6942,1514015675615,119 -6943,1514015728316,122 -6944,1514015817711,124 -6945,1514015946733,124 -6946,1514016455905,122 -6947,1514016493719,117 -6948,1514016534972,121 -6949,1514016672377,123 -6950,1514016841725,120 -6951,1514016875758,118 -6952,1514016991642,121 -6953,1514017669014,119 -6954,1514017847408,115 -6955,1514018061937,111 -6956,1514018279535,110 -6957,1514018623711,108 -6958,1514018641375,105 -6959,1514018662921,115 -6960,1514018696920,123 -6961,1514019050739,127 -6962,1514019559621,123 -6963,1514020117783,119 -6964,1514020122661,114 -6965,1514020715705,166 -6966,1514020732897,169 -6967,1514020903273,187 -6968,1514021105005,185 -6969,1514021318654,188 -6970,1514021742000,184 -6971,1514021798673,179 -6972,1514021918540,181 -6973,1514022022051,179 -6974,1514022432876,177 -6975,1514022981762,172 -6976,1514023426668,169 -6977,1514024019895,164 -6978,1514024525779,158 -6979,1514025138893,153 -6980,1514025280248,149 -6981,1514025505862,147 -6982,1514025885997,143 -6983,1514026870738,138 -6984,1514027689861,133 -6985,1514027921809,127 -6986,1514028217603,123 -6987,1514028369558,118 -6988,1514029008150,118 -6989,1514029019156,114 -6990,1514029030860,134 -6991,1514029041872,156 -6992,1514029275633,185 -6993,1514029997328,182 -6994,1514030291854,176 -6995,1514030299329,172 -6996,1514030317053,222 -6997,1514030720477,244 -6998,1514031421131,238 -6999,1514031546135,231 -7000,1514031863881,229 -7001,1514032221192,222 -7002,1514032802297,216 -7003,1514033037335,211 -7004,1514033387865,210 -7005,1514033973393,204 -7006,1514034039626,199 -7007,1514034294492,202 -7008,1514034762887,196 -7009,1514035209165,190 -7010,1514035835035,185 -7011,1514036518614,179 -7012,1514036868636,172 -7013,1514037238924,164 -7014,1514037404183,158 -7015,1514038163988,153 -7016,1514039937089,146 -7017,1514041966749,139 -7018,1514042290232,131 -7019,1514042343432,124 -7020,1514042517813,123 -7021,1514042656279,117 -7022,1514042667326,114 -7023,1514043069257,134 -7024,1514044064545,126 -7025,1514045752254,119 -7026,1514046459280,112 -7027,1514046470603,104 -7028,1514047109234,118 -7029,1514047796753,113 -7030,1514048223118,121 -7031,1514049098600,114 -7032,1514049600202,107 -7033,1514049823733,100 -7034,1514050528305,99 -7035,1514050643566,104 -7036,1514050703414,111 -7037,1514050785000,109 -7038,1514051037114,105 -7039,1514051099811,98 -7040,1514051512792,96 -7041,1514052232385,88 -7042,1514052598787,82 -7043,1514052633737,76 -7044,1514052856840,76 -7045,1514053382671,71 -7046,1514053806119,65 -7047,1514053868909,59 -7048,1514054021374,58 -7049,1514054291459,54 -7050,1514054295913,49 -7051,1514054370590,69 -7052,1514054479794,68 -7053,1514054503637,63 -7054,1514054527548,63 -7055,1514054623115,63 -7056,1514054741867,57 -7057,1514054944324,51 -7058,1514055303506,44 -7059,1514055360429,44 -7060,1514055521192,46 -7061,1514055763599,44 -7062,1514055816968,38 -7063,1514056153231,32 -7064,1514056476337,26 -7065,1514056565535,47 -7066,1514056693434,43 -7067,1514056819913,50 -7068,1514056850648,46 -7069,1514056889285,45 -7070,1514057113121,43 -7071,1514057206004,38 -7072,1514057386652,37 -7073,1514057554910,34 -7074,1514057585353,30 -7075,1514057685770,28 -7076,1514057767078,23 -7077,1514057788611,18 -7078,1514057867769,15 -7079,1514057892162,10 -7080,1514057906346,6 -7081,1514057921519,2 -7082,1514057926255,1 -7083,1514057935192,1 -7084,1514057939643,1 -7085,1514057943732,1 -7086,1514057947966,1 -7087,1514057952373,1 -7088,1514057961015,1 -7089,1514057965291,1 -7090,1514057969775,1 -7091,1514057981480,1 -7092,1514057985735,1 -7093,1514057990078,1 -7094,1514057999055,1 -7095,1514058007628,1 -7096,1514058011883,9 -7097,1514058046100,27 -7098,1514058084333,26 -7099,1514058162983,24 -7100,1514058183417,25 -7101,1514058194317,26 -7102,1514058288005,29 -7103,1514058311619,27 -7104,1514058379214,27 -7105,1514058419629,26 -7106,1514058484199,25 -7107,1514058522427,27 -7108,1514058533247,26 -7109,1514058547634,30 -7110,1514058731282,32 -7111,1514058791566,30 -7112,1514058838192,28 -7113,1514058887253,27 -7114,1514058905859,25 -7115,1514058978171,26 -7116,1514059012988,24 -7117,1514059046786,22 -7118,1514059081053,21 -7119,1514059085719,20 -7120,1514059129850,29 -7121,1514059417271,29 -7122,1514059510805,27 -7123,1514059626987,37 -7124,1514059689660,35 -7125,1514059703756,34 -7126,1514059805778,37 -7127,1514059836357,35 -7128,1514059887487,45 -7129,1514059911286,45 -7130,1514059962621,47 -7131,1514060115642,47 -7132,1514060381354,45 -7133,1514060402170,42 -7134,1514060486539,46 -7135,1514060516014,44 -7136,1514060527157,45 -7137,1514060586100,54 -7138,1514060778904,56 -7139,1514060844962,53 -7140,1514060869011,54 -7141,1514060906683,57 -7142,1514061022189,58 -7143,1514061042942,56 -7144,1514061420123,62 -7145,1514061431241,59 -7146,1514061507540,70 -7147,1514061715424,68 -7148,1514061975224,67 -7149,1514061982889,64 -7150,1514062021613,82 -7151,1514062289029,96 -7152,1514062652125,95 -7153,1514062923877,94 -7154,1514063015365,94 -7155,1514063183142,97 -7156,1514063396534,96 -7157,1514063658236,94 -7158,1514063776505,93 -7159,1514064025596,91 -7160,1514064167945,90 -7161,1514064186126,89 -7162,1514064325541,98 -7163,1514064567058,96 -7164,1514064643253,94 -7165,1514064888465,94 -7166,1514065307694,93 -7167,1514065381113,90 -7168,1514065507911,89 -7169,1514065551368,90 -7170,1514065668086,93 -7171,1514065795716,91 -7172,1514065855243,91 -7173,1514066109986,91 -7174,1514066444047,88 -7175,1514066789925,87 -7176,1514067204511,85 -7177,1514067384677,82 -7178,1514067746398,81 -7179,1514068169677,78 -7180,1514068256233,75 -7181,1514068310467,74 -7182,1514068404673,74 -7183,1514068532296,73 -7184,1514068586247,71 -7185,1514068719027,71 -7186,1514068798916,69 -7187,1514068943460,67 -7188,1514069160546,66 -7189,1514069500949,63 -7190,1514069528836,59 -7191,1514069575830,62 -7192,1514069725758,61 -7193,1514069756685,58 -7194,1514069861872,59 -7195,1514069995212,57 -7196,1514070133664,54 -7197,1514070184537,54 -7198,1514070199273,54 -7199,1514070217063,60 -7200,1514070254695,64 -7201,1514070282724,66 -7202,1514070320778,70 -7203,1514070355630,71 -7204,1514070386722,74 -7205,1514070436453,75 -7206,1514070574723,76 -7207,1514070783248,73 -7208,1514071184338,71 -7209,1514071267578,70 -7210,1514071285339,71 -7211,1514071346058,77 -7212,1514071538350,76 -7213,1514071864009,73 -7214,1514071878346,70 -7215,1514071980732,79 -7216,1514071989137,77 -7217,1514072138259,95 -7218,1514072340584,94 -7219,1514072580699,90 -7220,1514072588395,92 -7221,1514072827163,117 -7222,1514072929337,113 -7223,1514073193002,111 -7224,1514073516386,108 -7225,1514073875027,104 -7226,1514073966262,103 -7227,1514074091054,101 -7228,1514074298047,99 -7229,1514074670548,97 -7230,1514075227012,94 -7231,1514075231635,92 -7232,1514075347385,135 -7233,1514075396270,132 -7234,1514075620835,135 -7235,1514075922665,132 -7236,1514076087384,129 -7237,1514076151578,131 -7238,1514076686011,131 -7239,1514076903266,127 -7240,1514076924070,124 -7241,1514076941402,135 -7242,1514077082167,151 -7243,1514077437452,147 -7244,1514077888884,146 -7245,1514078235593,141 -7246,1514078698343,143 -7247,1514078738689,139 -7248,1514078798246,142 -7249,1514078884201,143 -7250,1514079075741,152 -7251,1514079511568,151 -7252,1514079765638,146 -7253,1514080291213,142 -7254,1514080550895,138 -7255,1514080938285,135 -7256,1514081119473,131 -7257,1514081496967,128 -7258,1514081501658,124 -7259,1514081653333,183 -7260,1514082029217,179 -7261,1514082703225,175 -7262,1514083164725,176 -7263,1514083739158,171 -7264,1514084021247,166 -7265,1514084106680,162 -7266,1514084509284,161 -7267,1514085238496,156 -7268,1514085590122,152 -7269,1514085664918,148 -7270,1514085821805,149 -7271,1514086287697,145 -7272,1514086809689,141 -7273,1514087440310,137 -7274,1514087814952,132 -7275,1514087988892,127 -7276,1514088053204,124 -7277,1514088234148,121 -7278,1514088439611,118 -7279,1514088469722,113 -7280,1514088850463,116 -7281,1514089245334,111 -7282,1514089455425,108 -7283,1514089500336,104 -7284,1514089552177,103 -7285,1514090020682,103 -7286,1514090080344,98 -7287,1514090283832,96 -7288,1514090669253,92 -7289,1514091021716,87 -7290,1514091305009,81 -7291,1514091890737,77 -7292,1514092178477,73 -7293,1514092460391,68 -7294,1514092522651,65 -7295,1514092673359,61 -7296,1514092789211,57 -7297,1514092969780,52 -7298,1514093121282,48 -7299,1514093151799,47 -7300,1514093193267,48 -7301,1514093421991,47 -7302,1514093571881,45 -7303,1514093641285,42 -7304,1514093723649,40 -7305,1514093728180,38 -7306,1514093749158,54 -7307,1514093777760,54 -7308,1514093857176,54 -7309,1514093958931,49 -7310,1514094107323,45 -7311,1514094135873,45 -7312,1514094228511,44 -7313,1514094475305,39 -7314,1514094552045,35 -7315,1514094659592,36 -7316,1514094674075,32 -7317,1514094692917,42 -7318,1514094766961,43 -7319,1514094805252,39 -7320,1514094930725,36 -7321,1514094955143,46 -7322,1514094969422,46 -7323,1514094983849,50 -7324,1514095021530,52 -7325,1514095113449,51 -7326,1514095190243,48 -7327,1514095230367,44 -7328,1514095264856,42 -7329,1514095308900,40 -7330,1514095365841,38 -7331,1514095466943,33 -7332,1514095503959,54 -7333,1514095583686,53 -7334,1514095626947,54 -7335,1514095799840,52 -7336,1514095960908,49 -7337,1514096099070,45 -7338,1514096143058,44 -7339,1514096212567,41 -7340,1514096250198,39 -7341,1514096267516,44 -7342,1514096330451,55 -7343,1514096489811,55 -7344,1514096517178,51 -7345,1514096558738,52 -7346,1514096569817,50 -7347,1514096591771,57 -7348,1514096750107,63 -7349,1514096822952,62 -7350,1514097083272,61 -7351,1514097104218,59 -7352,1514097111949,61 -7353,1514097130364,76 -7354,1514097173321,82 -7355,1514097312374,82 -7356,1514097339960,78 -7357,1514097369835,81 -7358,1514097508070,83 -7359,1514097665366,112 -7360,1514097777306,110 -7361,1514097852577,109 -7362,1514098141864,109 -7363,1514098297950,106 -7364,1514098357521,103 -7365,1514098677685,104 -7366,1514098784843,103 -7367,1514099112054,101 -7368,1514099152029,98 -7369,1514099242796,99 -7370,1514099342787,100 -7371,1514099475733,99 -7372,1514099590091,97 -7373,1514099751484,95 -7374,1514099836173,93 -7375,1514100018410,91 -7376,1514100075075,88 -7377,1514100087792,90 -7378,1514100266586,104 -7379,1514100280707,101 -7380,1514100302862,118 -7381,1514100366022,126 -7382,1514100968348,126 -7383,1514101172275,122 -7384,1514101186814,122 -7385,1514101897247,140 -7386,1514102221112,135 -7387,1514102745389,133 -7388,1514102839835,129 -7389,1514103067927,127 -7390,1514103353976,123 -7391,1514103862927,119 -7392,1514104028151,115 -7393,1514104476433,111 -7394,1514104932295,107 -7395,1514104985745,104 -7396,1514105273929,104 -7397,1514105414863,100 -7398,1514105649149,96 -7399,1514106189744,93 -7400,1514106346108,90 -7401,1514106384049,87 -7402,1514106475427,88 -7403,1514106486824,85 -7404,1514106567315,99 -7405,1514106595023,97 -7406,1514107101674,110 -7407,1514107395736,108 -7408,1514107691000,106 -7409,1514108001091,102 -7410,1514108446136,98 -7411,1514108502276,94 -7412,1514108694270,95 -7413,1514108832202,91 -7414,1514108836551,87 -7415,1514109142186,131 -7416,1514109452030,127 -7417,1514109884081,124 -7418,1514110134389,122 -7419,1514110407003,117 -7420,1514110462086,114 -7421,1514110830807,114 -7422,1514110940078,111 -7423,1514111148078,112 -7424,1514111263283,111 -7425,1514111300127,109 -7426,1514111307519,111 -7427,1514111358598,143 -7428,1514111445460,144 -7429,1514111799821,143 -7430,1514112236197,139 -7431,1514112602878,135 -7432,1514112669293,130 -7433,1514112693086,130 -7434,1514112786156,137 -7435,1514113033934,136 -7436,1514113946706,132 -7437,1514114200538,125 -7438,1514114707306,120 -7439,1514114946683,115 -7440,1514115189615,111 -7441,1514115338874,106 -7442,1514115476980,104 -7443,1514115923788,102 -7444,1514116541975,96 -7445,1514116567037,92 -7446,1514116640902,97 -7447,1514116791542,99 -7448,1514116869114,98 -7449,1514117070005,95 -7450,1514117238559,90 -7451,1514117487347,86 -7452,1514117671355,84 -7453,1514117724527,89 -7454,1514117738756,92 -7455,1514117944714,104 -7456,1514118258844,100 -7457,1514118426261,98 -7458,1514118915090,97 -7459,1514118932555,92 -7460,1514119195106,101 -7461,1514119349734,97 -7462,1514119644494,94 -7463,1514119884550,89 -7464,1514120225162,85 -7465,1514120493549,82 -7466,1514120806755,77 -7467,1514121071334,73 -7468,1514121561227,68 -7469,1514121690092,66 -7470,1514121896818,62 -7471,1514122049756,59 -7472,1514122057529,55 -7473,1514122087738,67 -7474,1514122269005,68 -7475,1514122299855,64 -7476,1514122387222,64 -7477,1514122475553,62 -7478,1514122593784,66 -7479,1514122702418,62 -7480,1514122723289,66 -7481,1514122806345,75 -7482,1514122852642,74 -7483,1514122863565,73 -7484,1514122950066,85 -7485,1514123086269,92 -7486,1514123163147,88 -7487,1514123279654,86 -7488,1514123583946,83 -7489,1514123618775,80 -7490,1514123662839,80 -7491,1514123733134,80 -7492,1514123860547,78 -7493,1514124206628,74 -7494,1514124472928,69 -7495,1514124507786,65 -7496,1514124616145,66 -7497,1514124670772,63 -7498,1514124856678,60 -7499,1514124913462,56 -7500,1514125064176,54 -7501,1514125118199,50 -7502,1514125209752,49 -7503,1514125226956,45 -7504,1514125258588,56 -7505,1514125368952,56 -7506,1514125450991,56 -7507,1514125581187,53 -7508,1514125764008,49 -7509,1514125883906,45 -7510,1514125949356,41 -7511,1514125995011,38 -7512,1514126019069,36 -7513,1514126119770,36 -7514,1514126303557,32 -7515,1514126433960,52 -7516,1514126587520,48 -7517,1514126669811,45 -7518,1514126750048,43 -7519,1514126861694,40 -7520,1514127006939,36 -7521,1514127129320,35 -7522,1514127421348,32 -7523,1514127455955,29 -7524,1514127482503,27 -7525,1514127520241,26 -7526,1514127554176,27 -7527,1514127659321,44 -7528,1514127906721,43 -7529,1514127947333,43 -7530,1514128019204,42 -7531,1514128023645,40 -7532,1514128080581,58 -7533,1514128256592,59 -7534,1514128290065,63 -7535,1514128324009,65 -7536,1514128391380,66 -7537,1514128459548,64 -7538,1514128558632,64 -7539,1514128777051,62 -7540,1514128828089,60 -7541,1514128933638,58 -7542,1514129069820,57 -7543,1514129115134,55 -7544,1514129223623,54 -7545,1514129279691,52 -7546,1514129325441,54 -7547,1514129450483,55 -7548,1514129611853,52 -7549,1514129616486,51 -7550,1514129681771,74 -7551,1514129713417,73 -7552,1514129961226,75 -7553,1514129989516,71 -7554,1514130019855,75 -7555,1514130269550,85 -7556,1514130306324,82 -7557,1514130459374,84 -7558,1514130588308,81 -7559,1514130707268,79 -7560,1514130843266,83 -7561,1514130986044,80 -7562,1514131044641,79 -7563,1514131073632,78 -7564,1514131131357,80 -7565,1514131205449,80 -7566,1514131255746,79 -7567,1514131348394,79 -7568,1514131505945,76 -7569,1514131638179,73 -7570,1514131780430,71 -7571,1514131877322,68 -7572,1514131974900,65 -7573,1514132056605,72 -7574,1514132393679,72 -7575,1514132404774,69 -7576,1514132483088,83 -7577,1514132615855,82 -7578,1514132623530,80 -7579,1514132786179,101 -7580,1514132928898,98 -7581,1514132966659,99 -7582,1514133053509,102 -7583,1514133219962,102 -7584,1514133474544,108 -7585,1514133998161,106 -7586,1514134078013,102 -7587,1514134204747,103 -7588,1514134442389,101 -7589,1514134694904,98 -7590,1514134931226,97 -7591,1514135217842,96 -7592,1514135483647,94 -7593,1514135761235,91 -7594,1514135973549,88 -7595,1514136108372,85 -7596,1514136204881,85 -7597,1514136479465,83 -7598,1514136917182,82 -7599,1514137004506,78 -7600,1514137098488,78 -7601,1514137102800,75 -7602,1514137526670,114 -7603,1514137656712,111 -7604,1514137770554,111 -7605,1514138284895,111 -7606,1514138825487,108 -7607,1514139015338,104 -7608,1514139261038,102 -7609,1514139368566,98 -7610,1514139392654,96 -7611,1514139591213,102 -7612,1514139830404,99 -7613,1514140280154,97 -7614,1514140496029,93 -7615,1514140639205,89 -7616,1514140908521,87 -7617,1514140936169,83 -7618,1514141003166,86 -7619,1514141169248,86 -7620,1514141362157,82 -7621,1514141476979,78 -7622,1514141684797,76 -7623,1514141895168,72 -7624,1514141932093,69 -7625,1514142165841,70 -7626,1514142272120,66 -7627,1514142282947,64 -7628,1514142426754,74 -7629,1514142688556,70 -7630,1514142766494,67 -7631,1514142902755,65 -7632,1514143055702,72 -7633,1514143086122,69 -7634,1514143265133,71 -7635,1514143440069,69 -7636,1514143463918,68 -7637,1514143584667,71 -7638,1514144030807,69 -7639,1514144187519,65 -7640,1514144467718,61 -7641,1514144548658,59 -7642,1514144608881,56 -7643,1514144727435,54 -7644,1514144780465,52 -7645,1514144827031,50 -7646,1514144875235,50 -7647,1514145111392,49 -7648,1514145247949,45 -7649,1514145341442,42 -7650,1514145391332,51 -7651,1514145504935,51 -7652,1514145630708,51 -7653,1514145722974,47 -7654,1514145895294,48 -7655,1514146132593,47 -7656,1514146162584,44 -7657,1514146227405,45 -7658,1514146285461,44 -7659,1514146426229,43 -7660,1514146451896,40 -7661,1514146528833,41 -7662,1514146585883,38 -7663,1514146717857,37 -7664,1514146808876,37 -7665,1514146880453,36 -7666,1514146975120,35 -7667,1514147084366,33 -7668,1514147217516,31 -7669,1514147315174,28 -7670,1514147378761,26 -7671,1514147452422,23 -7672,1514147486022,21 -7673,1514147522800,19 -7674,1514147556423,18 -7675,1514147594284,16 -7676,1514147630923,21 -7677,1514147691289,20 -7678,1514147745594,18 -7679,1514147809998,28 -7680,1514147940883,26 -7681,1514148000704,25 -7682,1514148005472,25 -7683,1514148125676,36 -7684,1514148193126,35 -7685,1514148220546,33 -7686,1514148247515,33 -7687,1514148268845,34 -7688,1514148352613,35 -7689,1514148409875,33 -7690,1514148476698,32 -7691,1514148526429,30 -7692,1514148561104,29 -7693,1514148660381,28 -7694,1514148744726,26 -7695,1514148814595,23 -7696,1514148905227,22 -7697,1514148916573,20 -7698,1514148957855,21 -7699,1514148996258,20 -7700,1514149040948,18 -7701,1514149092959,16 -7702,1514149150893,36 -7703,1514149182580,34 -7704,1514149289265,36 -7705,1514149468809,35 -7706,1514149476564,33 -7707,1514149487397,40 -7708,1514149624629,47 -7709,1514149702578,46 -7710,1514149791956,44 -7711,1514149830452,48 -7712,1514149868558,48 -7713,1514149922738,49 -7714,1514149959762,47 -7715,1514150009046,48 -7716,1514150084916,48 -7717,1514150089448,49 -7718,1514150113485,75 -7719,1514150344827,81 -7720,1514150416519,79 -7721,1514150550673,78 -7722,1514150677430,77 -7723,1514150756099,76 -7724,1514150852428,76 -7725,1514151034022,76 -7726,1514151413843,74 -7727,1514151533563,72 -7728,1514151719146,77 -7729,1514151741588,76 -7730,1514151795952,81 -7731,1514151934581,83 -7732,1514152130823,81 -7733,1514152277747,80 -7734,1514152368312,81 -7735,1514152652662,80 -7736,1514152674655,77 -7737,1514152923247,86 -7738,1514153642779,85 -7739,1514153747872,82 -7740,1514153781424,81 -7741,1514153987963,83 -7742,1514154166647,82 -7743,1514154319367,81 -7744,1514154510171,79 -7745,1514154886350,78 -7746,1514154939035,76 -7747,1514155104401,78 -7748,1514155306524,76 -7749,1514155463597,74 -7750,1514155484504,73 -7751,1514155542361,79 -7752,1514155720070,79 -7753,1514155822619,77 -7754,1514155932390,76 -7755,1514156024206,75 -7756,1514156124075,74 -7757,1514156278238,74 -7758,1514156444455,72 -7759,1514156754238,71 -7760,1514156761794,68 -7761,1514156986836,88 -7762,1514157170621,86 -7763,1514157393002,85 -7764,1514157511774,82 -7765,1514157621949,80 -7766,1514157746138,80 -7767,1514157750742,78 -7768,1514157786191,114 -7769,1514157886281,119 -7770,1514157903898,117 -7771,1514158361412,129 -7772,1514158727202,125 -7773,1514159008391,122 -7774,1514159188729,119 -7775,1514159255296,117 -7776,1514159544873,117 -7777,1514159953200,113 -7778,1514159963890,110 -7779,1514160077151,130 -7780,1514160415424,128 -7781,1514160753960,124 -7782,1514161108853,121 -7783,1514161424376,123 -7784,1514161785310,119 -7785,1514161872052,116 -7786,1514161920274,116 -7787,1514161938175,118 -7788,1514162418333,131 -7789,1514162429401,127 -7790,1514162617017,150 -7791,1514162634989,147 -7792,1514163130701,162 -7793,1514163438669,157 -7794,1514163595945,153 -7795,1514163984384,150 -7796,1514165265229,146 -7797,1514165336285,140 -7798,1514165498790,141 -7799,1514165578679,138 -7800,1514166176469,137 -7801,1514166210682,132 -7802,1514166595592,136 -7803,1514167559445,132 -7804,1514167939484,127 -7805,1514168272069,122 -7806,1514168397415,117 -7807,1514168452708,119 -7808,1514168551064,123 -7809,1514168775134,121 -7810,1514169115806,116 -7811,1514169124057,112 -7812,1514169271244,141 -7813,1514169505788,137 -7814,1514169526533,134 -7815,1514169626369,145 -7816,1514169831440,143 -7817,1514169983434,140 -7818,1514170091331,148 -7819,1514170285675,150 -7820,1514171051396,145 -7821,1514171302520,141 -7822,1514171392654,137 -7823,1514171620038,136 -7824,1514171968633,132 -7825,1514172125234,128 -7826,1514172482541,124 -7827,1514172761167,119 -7828,1514172863472,115 -7829,1514173313193,112 -7830,1514173711585,111 -7831,1514173839155,107 -7832,1514173993670,104 -7833,1514174075572,100 -7834,1514174147671,98 -7835,1514174824839,96 -7836,1514174990863,91 -7837,1514175338922,91 -7838,1514175525865,86 -7839,1514175708159,81 -7840,1514175872504,78 -7841,1514176042489,75 -7842,1514176219677,71 -7843,1514176313021,67 -7844,1514176377132,63 -7845,1514176398783,60 -7846,1514176613315,62 -7847,1514176922449,58 -7848,1514177099813,54 -7849,1514177191185,49 -7850,1514177224798,45 -7851,1514177251198,46 -7852,1514177273271,47 -7853,1514177287639,46 -7854,1514177314800,48 -7855,1514177466281,48 -7856,1514177717781,44 -7857,1514177792038,39 -7858,1514177860167,35 -7859,1514177933206,31 -7860,1514177957111,26 -7861,1514178133496,34 -7862,1514178204333,29 -7863,1514178228663,25 -7864,1514178268652,22 -7865,1514178320738,19 -7866,1514178411332,15 -7867,1514178435173,10 -7868,1514178439764,26 -7869,1514178530376,39 -7870,1514178553434,36 -7871,1514178767316,43 -7872,1514178811074,39 -7873,1514178822522,37 -7874,1514178905100,40 -7875,1514178946880,37 -7876,1514178992311,36 -7877,1514179021089,34 -7878,1514179113366,32 -7879,1514179124367,40 -7880,1514179154551,45 -7881,1514179437827,44 -7882,1514179568204,40 -7883,1514179589710,37 -7884,1514179681364,36 -7885,1514179754306,33 -7886,1514179772960,31 -7887,1514179797924,33 -7888,1514179844949,40 -7889,1514179898014,37 -7890,1514179971103,49 -7891,1514180034239,47 -7892,1514180162160,55 -7893,1514180321098,52 -7894,1514180424862,49 -7895,1514180642937,48 -7896,1514180825576,45 -7897,1514180866254,42 -7898,1514181017315,42 -7899,1514181028403,40 -7900,1514181066640,47 -7901,1514181132786,47 -7902,1514181165389,49 -7903,1514181241683,49 -7904,1514181322619,47 -7905,1514181366174,44 -7906,1514181442646,43 -7907,1514181569491,42 -7908,1514181630222,42 -7909,1514181678215,40 -7910,1514181778003,39 -7911,1514181895731,37 -7912,1514182062594,51 -7913,1514182159182,49 -7914,1514182270131,48 -7915,1514182390670,53 -7916,1514182617245,53 -7917,1514182861802,52 -7918,1514183025341,50 -7919,1514183029882,49 -7920,1514183131184,73 -7921,1514183198389,71 -7922,1514183349036,71 -7923,1514183509636,71 -7924,1514183631953,69 -7925,1514183810444,67 -7926,1514183881076,66 -7927,1514183950998,66 -7928,1514184163802,64 -7929,1514184310130,63 -7930,1514184656252,61 -7931,1514184732630,58 -7932,1514185027874,58 -7933,1514185332930,55 -7934,1514185379212,54 -7935,1514185443354,56 -7936,1514185468968,55 -7937,1514185615089,56 -7938,1514185767430,55 -7939,1514185936864,52 -7940,1514186111572,51 -7941,1514186156354,48 -7942,1514186342272,48 -7943,1514186366343,46 -7944,1514186419440,47 -7945,1514186546279,47 -7946,1514186612813,48 -7947,1514186646256,46 -7948,1514186717154,47 -7949,1514186821248,46 -7950,1514186933370,44 -7951,1514187050842,43 -7952,1514187158855,42 -7953,1514187206455,43 -7954,1514187263570,45 -7955,1514187294190,46 -7956,1514187685357,47 -7957,1514187702663,44 -7958,1514187787322,48 -7959,1514187961771,47 -7960,1514188135366,45 -7961,1514188711644,43 -7962,1514189120093,41 -7963,1514189213051,37 -7964,1514189233678,37 -7965,1514189270509,38 -7966,1514189353799,38 -7967,1514189506267,36 -7968,1514189517055,34 -7969,1514189631625,45 -7970,1514189747735,43 -7971,1514189890025,43 -7972,1514190125703,40 -7973,1514190156305,39 -7974,1514190231973,43 -7975,1514190316404,42 -7976,1514190414146,41 -7977,1514190568566,40 -7978,1514190736797,39 -7979,1514190821525,37 -7980,1514190892511,39 -7981,1514190966164,39 -7982,1514191017974,38 -7983,1514191109281,37 -7984,1514191219106,38 -7985,1514191402984,36 -7986,1514191548719,34 -7987,1514191552987,34 -7988,1514191597573,52 -7989,1514191631078,52 -7990,1514191718617,55 -7991,1514192009984,54 -7992,1514192257238,51 -7993,1514192275273,50 -7994,1514192297043,54 -7995,1514192482041,57 -7996,1514192732110,55 -7997,1514193057528,53 -7998,1514193377711,51 -7999,1514193546594,49 -8000,1514193668014,51 -8001,1514193779179,50 -8002,1514193897944,49 -8003,1514193940839,48 -8004,1514194206438,48 -8005,1514194479619,47 -8006,1514194590584,46 -8007,1514194610805,45 -8008,1514194641241,48 -8009,1514194707260,49 -8010,1514194794488,49 -8011,1514194808632,48 -8012,1514194949670,53 -8013,1514195155060,52 -8014,1514195288479,49 -8015,1514195293049,47 -8016,1514195533943,70 -8017,1514195699724,68 -8018,1514195917010,65 -8019,1514196033090,63 -8020,1514196199460,73 -8021,1514196559288,72 -8022,1514197252939,71 -8023,1514197490739,69 -8024,1514197639391,67 -8025,1514197821034,65 -8026,1514197950669,64 -8027,1514197987813,63 -8028,1514198075792,65 -8029,1514198136636,64 -8030,1514198304373,65 -8031,1514198497642,62 -8032,1514198871381,61 -8033,1514199239338,58 -8034,1514199277217,56 -8035,1514199346942,57 -8036,1514199437244,57 -8037,1514199477347,58 -8038,1514199497608,60 -8039,1514199541332,64 -8040,1514199620669,64 -8041,1514199684120,63 -8042,1514199726623,64 -8043,1514199847107,65 -8044,1514200235394,65 -8045,1514200715880,64 -8046,1514200746091,61 -8047,1514200760280,63 -8048,1514200811765,72 -8049,1514200825690,73 -8050,1514201086057,83 -8051,1514201400087,81 -8052,1514201696976,78 -8053,1514201920489,75 -8054,1514202294189,74 -8055,1514202499785,72 -8056,1514202507355,71 -8057,1514202790768,91 -8058,1514203180323,91 -8059,1514203501651,88 -8060,1514203884051,85 -8061,1514204205212,82 -8062,1514204209493,79 -8063,1514204259899,120 -8064,1514204785436,121 -8065,1514205020404,120 -8066,1514205122546,118 -8067,1514205304752,116 -8068,1514206000693,114 -8069,1514207162252,114 -8070,1514207179447,111 -8071,1514207206950,123 -8072,1514207277381,129 -8073,1514207510670,129 -8074,1514207632707,126 -8075,1514208150066,125 -8076,1514208568740,122 -8077,1514208666181,118 -8078,1514209349943,116 -8079,1514210040388,113 -8080,1514210770235,109 -8081,1514211711129,105 -8082,1514212237288,101 -8083,1514212659318,98 -8084,1514213255110,94 -8085,1514213872640,90 -8086,1514214368390,86 -8087,1514214798554,82 -8088,1514215742682,87 -8089,1514216483574,85 -8090,1514216681170,82 -8091,1514216765807,80 -8092,1514217238635,78 -8093,1514217314507,75 -8094,1514217449377,76 -8095,1514217557563,76 -8096,1514217594574,74 -8097,1514217807609,75 -8098,1514218028341,72 -8099,1514218175515,68 -8100,1514218324225,65 -8101,1514218443714,63 -8102,1514218533471,60 -8103,1514218576311,58 -8104,1514218611313,59 -8105,1514218744865,59 -8106,1514218860732,55 -8107,1514218875112,53 -8108,1514219108502,60 -8109,1514219205622,58 -8110,1514219433638,56 -8111,1514219663654,53 -8112,1514219681265,53 -8113,1514219700255,57 -8114,1514220004759,60 -8115,1514220025477,56 -8116,1514220091350,71 -8117,1514220137886,70 -8118,1514220409774,69 -8119,1514220927463,67 -8120,1514221174903,63 -8121,1514221345196,60 -8122,1514221350020,57 -8123,1514221712933,82 -8124,1514222111357,77 -8125,1514222553673,74 -8126,1514223032046,70 -8127,1514223345722,67 -8128,1514223564987,64 -8129,1514223616261,61 -8130,1514223696652,61 -8131,1514223744063,59 -8132,1514223937118,57 -8133,1514224156365,54 -8134,1514224498114,50 -8135,1514224827690,47 -8136,1514225079114,45 -8137,1514225274036,41 -8138,1514225335305,38 -8139,1514225389620,39 -8140,1514225454927,38 -8141,1514225462532,36 -8142,1514225476746,45 -8143,1514225492364,50 -8144,1514225578903,54 -8145,1514225741615,51 -8146,1514225993722,47 -8147,1514226186447,45 -8148,1514226296403,46 -8149,1514226433416,45 -8150,1514226531312,48 -8151,1514226727395,45 -8152,1514227099844,41 -8153,1514227356054,38 -8154,1514227360322,35 -8155,1514227383577,51 -8156,1514227501673,51 -8157,1514227522132,59 -8158,1514227577486,63 -8159,1514227674234,61 -8160,1514227791142,59 -8161,1514227855006,55 -8162,1514227958175,54 -8163,1514228086260,73 -8164,1514228152773,73 -8165,1514228247497,73 -8166,1514228346349,71 -8167,1514228657093,71 -8168,1514228968387,69 -8169,1514229095525,66 -8170,1514229215091,64 -8171,1514229309521,69 -8172,1514229557629,73 -8173,1514229895138,72 -8174,1514230402791,70 -8175,1514230649390,68 -8176,1514230758609,66 -8177,1514230807415,65 -8178,1514230894312,66 -8179,1514231108443,65 -8180,1514231268148,63 -8181,1514231437429,60 -8182,1514231451320,58 -8183,1514231475084,65 -8184,1514231533212,68 -8185,1514231956712,67 -8186,1514232099065,64 -8187,1514232148054,62 -8188,1514232184195,62 -8189,1514232580142,62 -8190,1514232655812,59 -8191,1514232664543,58 -8192,1514233057563,71 -8193,1514233322402,68 -8194,1514233420304,65 -8195,1514233606528,64 -8196,1514233860458,61 -8197,1514234048159,61 -8198,1514234157443,58 -8199,1514234184758,56 -8200,1514234373880,58 -8201,1514234378486,55 -8202,1514234521021,80 -8203,1514234559560,78 -8204,1514234759483,80 -8205,1514234893429,79 -8206,1514235199376,77 -8207,1514235362638,73 -8208,1514235696131,75 -8209,1514236072067,72 -8210,1514236173947,68 -8211,1514236310717,66 -8212,1514236362732,63 -8213,1514236566316,66 -8214,1514236820006,66 -8215,1514236935286,63 -8216,1514236992792,63 -8217,1514237148564,63 -8218,1514237198203,63 -8219,1514237255782,62 -8220,1514237410987,61 -8221,1514237451047,58 -8222,1514237522266,58 -8223,1514237573323,70 -8224,1514237615519,70 -8225,1514237927450,71 -8226,1514238216402,68 -8227,1514238286916,65 -8228,1514238419919,64 -8229,1514238530209,62 -8230,1514238731964,60 -8231,1514239453719,59 -8232,1514240114143,57 -8233,1514240391729,53 -8234,1514240906310,50 -8235,1514241160975,47 -8236,1514241332335,44 -8237,1514241353123,41 -8238,1514241400829,42 -8239,1514241435382,41 -8240,1514241641472,42 -8241,1514241855683,39 -8242,1514242021698,42 -8243,1514242193381,42 -8244,1514242250980,43 -8245,1514242326435,43 -8246,1514242389410,41 -8247,1514242462300,39 -8248,1514242661553,38 -8249,1514242692475,35 -8250,1514242798661,35 -8251,1514242806863,33 -8252,1514242815227,39 -8253,1514242837097,47 -8254,1514243078723,49 -8255,1514243140053,56 -8256,1514243203838,56 -8257,1514243342476,57 -8258,1514243642043,58 -8259,1514244032713,55 -8260,1514244520250,54 -8261,1514244990492,51 -8262,1514245301233,49 -8263,1514245611553,47 -8264,1514245918145,44 -8265,1514246092409,43 -8266,1514246281745,42 -8267,1514246406045,39 -8268,1514246464728,37 -8269,1514246529322,36 -8270,1514246686371,35 -8271,1514246878632,33 -8272,1514246949765,31 -8273,1514247095291,29 -8274,1514247240367,26 -8275,1514247263632,24 -8276,1514247282812,23 -8277,1514247331109,24 -8278,1514247407580,23 -8279,1514247474014,22 -8280,1514247573572,20 -8281,1514247673592,18 -8282,1514247706238,15 -8283,1514247734080,18 -8284,1514247766010,20 -8285,1514247780890,21 -8286,1514247978869,21 -8287,1514248088174,18 -8288,1514248140574,17 -8289,1514248188192,18 -8290,1514248233477,15 -8291,1514248278530,15 -8292,1514248303154,20 -8293,1514248335060,20 -8294,1514248376663,20 -8295,1514248401864,19 -8296,1514248417213,19 -8297,1514248472112,19 -8298,1514248529021,18 -8299,1514248561145,16 -8300,1514248589134,17 -8301,1514248608609,16 -8302,1514248662965,30 -8303,1514248714234,30 -8304,1514248729138,31 -8305,1514248803039,35 -8306,1514248877299,35 -8307,1514248905124,33 -8308,1514248934163,35 -8309,1514248948823,36 -8310,1514248992725,40 -8311,1514249076386,40 -8312,1514249199686,39 -8313,1514249522192,39 -8314,1514249803803,38 -8315,1514249871226,35 -8316,1514249959505,35 -8317,1514250190364,35 -8318,1514250383253,34 -8319,1514250622757,33 -8320,1514250871558,32 -8321,1514250904051,30 -8322,1514250934900,32 -8323,1514250997349,33 -8324,1514251048687,34 -8325,1514251145329,36 -8326,1514251340973,35 -8327,1514251522328,33 -8328,1514251597944,33 -8329,1514251702305,32 -8330,1514251821803,31 -8331,1514251915839,30 -8332,1514252083099,29 -8333,1514252189227,27 -8334,1514252256808,26 -8335,1514252361940,25 -8336,1514252511088,23 -8337,1514252703548,22 -8338,1514252801597,22 -8339,1514252816545,22 -8340,1514252854584,25 -8341,1514252890219,25 -8342,1514252911713,24 -8343,1514252947088,26 -8344,1514252972004,25 -8345,1514253001137,26 -8346,1514253092887,27 -8347,1514253366398,26 -8348,1514253602732,25 -8349,1514253710143,24 -8350,1514253791998,23 -8351,1514253839892,22 -8352,1514253930381,26 -8353,1514254015385,31 -8354,1514254168835,31 -8355,1514254298800,31 -8356,1514254343923,31 -8357,1514254461798,31 -8358,1514254572427,31 -8359,1514254690009,30 -8360,1514254787515,29 -8361,1514254985091,28 -8362,1514255204916,27 -8363,1514255271486,26 -8364,1514255378346,25 -8365,1514255491353,24 -8366,1514255541902,23 -8367,1514255604434,22 -8368,1514255732130,22 -8369,1514255877660,21 -8370,1514255976714,21 -8371,1514256038146,19 -8372,1514256096329,19 -8373,1514256147861,18 -8374,1514256191631,18 -8375,1514256238362,17 -8376,1514256361765,18 -8377,1514256483668,17 -8378,1514256515400,17 -8379,1514256583827,16 -8380,1514256639830,16 -8381,1514256687686,15 -8382,1514256746196,15 -8383,1514256835593,14 -8384,1514256903740,14 -8385,1514256955564,13 -8386,1514256991175,13 -8387,1514256999656,13 -8388,1514257097882,16 -8389,1514257226939,14 -8390,1514257290042,14 -8391,1514257325063,13 -8392,1514257385684,12 -8393,1514257440500,12 -8394,1514257456435,11 -8395,1514257505218,12 -8396,1514257555160,12 -8397,1514257577103,12 -8398,1514257608980,12 -8399,1514257634149,12 -8400,1514257655747,12 -8401,1514257677756,13 -8402,1514257712767,14 -8403,1514257799389,14 -8404,1514257875969,13 -8405,1514257934767,15 -8406,1514258012398,15 -8407,1514258058926,14 -8408,1514258089970,15 -8409,1514258121525,17 -8410,1514258140010,19 -8411,1514258204964,21 -8412,1514258282227,22 -8413,1514258326888,21 -8414,1514258365114,21 -8415,1514258390663,21 -8416,1514258493986,22 -8417,1514258610014,22 -8418,1514258674638,21 -8419,1514258774542,21 -8420,1514258834726,20 -8421,1514258864923,19 -8422,1514258922079,21 -8423,1514258983706,22 -8424,1514259018535,22 -8425,1514259036824,23 -8426,1514259048561,25 -8427,1514259119065,28 -8428,1514259229558,29 -8429,1514259286810,28 -8430,1514259383651,28 -8431,1514259505742,28 -8432,1514259626026,27 -8433,1514259776271,27 -8434,1514259847202,26 -8435,1514260031290,26 -8436,1514260259560,25 -8437,1514260372330,24 -8438,1514260421063,23 -8439,1514260481400,23 -8440,1514260549965,25 -8441,1514260604557,24 -8442,1514260632614,25 -8443,1514260718841,27 -8444,1514260795203,27 -8445,1514260851629,28 -8446,1514260925944,29 -8447,1514261016796,29 -8448,1514261146991,29 -8449,1514261287153,28 -8450,1514261381651,27 -8451,1514261442130,27 -8452,1514261552398,27 -8453,1514261637116,27 -8454,1514261800965,26 -8455,1514261988277,26 -8456,1514262104258,25 -8457,1514262215090,25 -8458,1514262274787,25 -8459,1514262304580,24 -8460,1514262316625,26 -8461,1514262338823,30 -8462,1514262392920,31 -8463,1514262489672,31 -8464,1514262609531,32 -8465,1514262670386,31 -8466,1514262761127,31 -8467,1514262837531,31 -8468,1514262869194,31 -8469,1514262943627,31 -8470,1514263008217,31 -8471,1514263073893,31 -8472,1514263159085,32 -8473,1514263232755,32 -8474,1514263267784,31 -8475,1514263416988,32 -8476,1514263578165,32 -8477,1514263815431,31 -8478,1514264141189,29 -8479,1514264266594,29 -8480,1514264337241,28 -8481,1514264486322,28 -8482,1514264580624,27 -8483,1514264628065,26 -8484,1514264695753,26 -8485,1514264762726,26 -8486,1514264882274,24 -8487,1514265011984,25 -8488,1514265139397,26 -8489,1514265243536,25 -8490,1514265344814,24 -8491,1514265542315,24 -8492,1514265672097,22 -8493,1514265735723,22 -8494,1514265858077,21 -8495,1514265941545,21 -8496,1514265993533,21 -8497,1514266060552,20 -8498,1514266096541,20 -8499,1514266129981,20 -8500,1514266141449,21 -8501,1514266214382,25 -8502,1514266294687,25 -8503,1514266321575,24 -8504,1514266352750,25 -8505,1514266387202,25 -8506,1514266466584,26 -8507,1514266573470,26 -8508,1514266654888,25 -8509,1514266702684,25 -8510,1514266733720,25 -8511,1514266779350,26 -8512,1514266847324,26 -8513,1514267121130,26 -8514,1514267355207,26 -8515,1514267433370,24 -8516,1514267549461,25 -8517,1514267699066,24 -8518,1514267802771,23 -8519,1514267824533,22 -8520,1514267843142,24 -8521,1514267868274,25 -8522,1514267932700,27 -8523,1514268124944,27 -8524,1514268296689,26 -8525,1514268339329,26 -8526,1514268505032,27 -8527,1514268670613,28 -8528,1514268701546,28 -8529,1514268720748,29 -8530,1514268747500,32 -8531,1514268878853,33 -8532,1514269021822,32 -8533,1514269069768,31 -8534,1514269218951,31 -8535,1514269371666,30 -8536,1514269459049,30 -8537,1514269531000,29 -8538,1514269657131,29 -8539,1514269779066,28 -8540,1514269853129,28 -8541,1514270006540,27 -8542,1514270170111,26 -8543,1514270410135,27 -8544,1514270644151,24 -8545,1514270698002,25 -8546,1514270765717,25 -8547,1514270842156,25 -8548,1514270870461,25 -8549,1514270882480,25 -8550,1514270920885,29 -8551,1514270995152,29 -8552,1514271217132,29 -8553,1514271426902,28 -8554,1514271468589,26 -8555,1514271494028,27 -8556,1514271512444,28 -8557,1514271580420,30 -8558,1514271648682,30 -8559,1514271683704,30 -8560,1514271783035,31 -8561,1514271861507,32 -8562,1514271889985,34 -8563,1514272019489,35 -8564,1514272139834,35 -8565,1514272164740,35 -8566,1514272236579,36 -8567,1514272314843,36 -8568,1514272370574,36 -8569,1514272423132,37 -8570,1514272451644,38 -8571,1514272541427,40 -8572,1514272678843,39 -8573,1514272833679,39 -8574,1514272937782,38 -8575,1514273218070,39 -8576,1514273552836,38 -8577,1514273664592,36 -8578,1514273682866,36 -8579,1514273855253,39 -8580,1514274062357,38 -8581,1514274191446,37 -8582,1514274233558,36 -8583,1514274292311,37 -8584,1514274346939,37 -8585,1514274514245,37 -8586,1514274677594,36 -8587,1514274747976,36 -8588,1514274799108,35 -8589,1514274866000,35 -8590,1514274918491,35 -8591,1514275157199,34 -8592,1514275394417,34 -8593,1514275612286,32 -8594,1514275920138,30 -8595,1514276037832,29 -8596,1514276121864,29 -8597,1514276204688,27 -8598,1514276230135,27 -8599,1514276258784,29 -8600,1514276287125,29 -8601,1514276426226,32 -8602,1514276569169,32 -8603,1514276755793,31 -8604,1514276936360,31 -8605,1514277010331,30 -8606,1514277097801,30 -8607,1514277142095,29 -8608,1514277175502,29 -8609,1514277298729,29 -8610,1514277505996,29 -8611,1514277669468,29 -8612,1514277747659,28 -8613,1514277791791,28 -8614,1514277855399,27 -8615,1514277890366,27 -8616,1514277918648,27 -8617,1514277969444,28 -8618,1514278001162,28 -8619,1514278130139,28 -8620,1514278243053,28 -8621,1514278315016,29 -8622,1514278390246,29 -8623,1514278415115,28 -8624,1514278440564,29 -8625,1514278542225,31 -8626,1514278728375,31 -8627,1514278839641,29 -8628,1514278996859,28 -8629,1514279190896,27 -8630,1514279277845,28 -8631,1514279399950,28 -8632,1514279523458,28 -8633,1514279561150,27 -8634,1514279592446,27 -8635,1514279656477,28 -8636,1514279782385,27 -8637,1514279915813,26 -8638,1514280018984,26 -8639,1514280125488,24 -8640,1514280245019,24 -8641,1514280339950,23 -8642,1514280396048,22 -8643,1514280440500,21 -8644,1514280476044,21 -8645,1514280524779,20 -8646,1514280556161,20 -8647,1514280662727,20 -8648,1514280756335,19 -8649,1514280887024,19 -8650,1514280958883,20 -8651,1514281016243,19 -8652,1514281043741,20 -8653,1514281146910,19 -8654,1514281167540,18 -8655,1514281231635,20 -8656,1514281299412,20 -8657,1514281308857,21 -8658,1514281407678,25 -8659,1514281497990,24 -8660,1514281527516,24 -8661,1514281603986,25 -8662,1514281664249,24 -8663,1514281757032,25 -8664,1514281826708,25 -8665,1514281885282,24 -8666,1514281912937,25 -8667,1514281955438,26 -8668,1514282009875,27 -8669,1514282082756,27 -8670,1514282219277,26 -8671,1514282246776,28 -8672,1514282306570,29 -8673,1514282367372,28 -8674,1514282445219,28 -8675,1514282508470,28 -8676,1514282550409,26 -8677,1514282588055,27 -8678,1514282676701,28 -8679,1514282918484,29 -8680,1514282962312,28 -8681,1514283020945,29 -8682,1514283117668,28 -8683,1514283166702,29 -8684,1514283260376,29 -8685,1514283364147,29 -8686,1514283385777,28 -8687,1514283435359,30 -8688,1514283498902,30 -8689,1514283506615,30 -8690,1514283511001,39 -8691,1514283625302,59 -8692,1514283630221,59 -8693,1514283756376,85 -8694,1514283860235,84 -8695,1514284004285,84 -8696,1514284282585,83 -8697,1514284628537,82 -8698,1514284653298,80 -8699,1514284799206,87 -8700,1514285029007,86 -8701,1514285277948,86 -8702,1514285423810,84 -8703,1514285665935,84 -8704,1514285716363,82 -8705,1514285873255,83 -8706,1514286152848,82 -8707,1514286603139,80 -8708,1514287360372,79 -8709,1514287699658,78 -8710,1514287968051,76 -8711,1514288140139,75 -8712,1514288234608,73 -8713,1514288313054,72 -8714,1514288529090,73 -8715,1514288827428,71 -8716,1514289010535,70 -8717,1514289147335,69 -8718,1514289179631,69 -8719,1514289269227,72 -8720,1514289507817,72 -8721,1514289710174,71 -8722,1514289755298,68 -8723,1514289982992,71 -8724,1514290292402,70 -8725,1514290525921,69 -8726,1514290665576,67 -8727,1514290874508,66 -8728,1514291229147,65 -8729,1514291402825,62 -8730,1514291434012,61 -8731,1514291465380,63 -8732,1514291609708,65 -8733,1514291670285,64 -8734,1514291723725,65 -8735,1514291797240,65 -8736,1514291992565,65 -8737,1514292077935,63 -8738,1514292428038,62 -8739,1514292712807,60 -8740,1514292752137,59 -8741,1514292906279,59 -8742,1514293065252,57 -8743,1514293146540,55 -8744,1514293319248,55 -8745,1514293492256,53 -8746,1514293582533,52 -8747,1514293635432,50 -8748,1514293683554,50 -8749,1514293745384,50 -8750,1514293847742,49 -8751,1514293975714,47 -8752,1514294086592,46 -8753,1514294297116,45 -8754,1514294488942,42 -8755,1514294531877,41 -8756,1514294573117,40 -8757,1514294678024,40 -8758,1514294749117,41 -8759,1514294757054,39 -8760,1514294792518,49 -8761,1514294823703,50 -8762,1514294904731,51 -8763,1514295147020,50 -8764,1514295232881,47 -8765,1514295293158,46 -8766,1514295347958,44 -8767,1514295469017,45 -8768,1514295618686,43 -8769,1514295930784,41 -8770,1514296413125,38 -8771,1514296431015,36 -8772,1514296460176,38 -8773,1514296476021,39 -8774,1514296554537,42 -8775,1514296597597,40 -8776,1514296733446,40 -8777,1514296820755,38 -8778,1514296840425,36 -8779,1514296898895,38 -8780,1514297010600,36 -8781,1514297045450,34 -8782,1514297230888,33 -8783,1514297314319,31 -8784,1514297325915,29 -8785,1514297378526,32 -8786,1514297455899,31 -8787,1514297705287,29 -8788,1514297851199,27 -8789,1514298007578,24 -8790,1514298104505,26 -8791,1514298227919,35 -8792,1514298326099,33 -8793,1514298376409,45 -8794,1514298461471,46 -8795,1514298506106,45 -8796,1514298560777,46 -8797,1514298629733,45 -8798,1514298694096,45 -8799,1514298778004,48 -8800,1514298925731,48 -8801,1514299131278,46 -8802,1514299273986,45 -8803,1514299431205,44 -8804,1514299569854,42 -8805,1514299709493,42 -8806,1514299884569,42 -8807,1514300228325,40 -8808,1514300555427,38 -8809,1514300787968,36 -8810,1514301028803,34 -8811,1514301219066,32 -8812,1514301265929,31 -8813,1514301307304,30 -8814,1514301474493,31 -8815,1514301642100,30 -8816,1514301703736,28 -8817,1514301806056,27 -8818,1514301943129,26 -8819,1514302054000,26 -8820,1514302180404,26 -8821,1514302354998,24 -8822,1514302484522,22 -8823,1514302600690,23 -8824,1514302737506,21 -8825,1514302789815,19 -8826,1514302831249,18 -8827,1514302850243,18 -8828,1514302878139,18 -8829,1514302912679,17 -8830,1514302974662,17 -8831,1514303015659,17 -8832,1514303034393,18 -8833,1514303049110,19 -8834,1514303070714,21 -8835,1514303143415,23 -8836,1514303280743,23 -8837,1514303384437,22 -8838,1514303460279,21 -8839,1514303528209,19 -8840,1514303628613,18 -8841,1514303708365,18 -8842,1514303747714,17 -8843,1514303800769,16 -8844,1514303899331,15 -8845,1514303997363,14 -8846,1514304021835,13 -8847,1514304052715,13 -8848,1514304087758,13 -8849,1514304117157,13 -8850,1514304166432,13 -8851,1514304197807,12 -8852,1514304231071,12 -8853,1514304258997,11 -8854,1514304284100,10 -8855,1514304306185,10 -8856,1514304324931,9 -8857,1514304347425,10 -8858,1514304368953,9 -8859,1514304390910,9 -8860,1514304409410,14 -8861,1514304425418,16 -8862,1514304450520,19 -8863,1514304574431,19 -8864,1514304704063,18 -8865,1514304769563,17 -8866,1514304815015,17 -8867,1514304826934,17 -8868,1514304842125,19 -8869,1514304864304,21 -8870,1514304886338,21 -8871,1514305046796,22 -8872,1514305259688,23 -8873,1514305351255,23 -8874,1514305383586,25 -8875,1514305540625,26 -8876,1514305661640,25 -8877,1514305758692,25 -8878,1514305813425,24 -8879,1514305950530,25 -8880,1514306169144,25 -8881,1514306292465,24 -8882,1514306337145,25 -8883,1514306453813,24 -8884,1514306580909,23 -8885,1514306660836,26 -8886,1514306761124,26 -8887,1514306887768,25 -8888,1514306964390,24 -8889,1514307041010,23 -8890,1514307163122,23 -8891,1514307236968,22 -8892,1514307284390,22 -8893,1514307332298,22 -8894,1514307348744,23 -8895,1514307402963,26 -8896,1514307464922,26 -8897,1514307566053,27 -8898,1514307803164,27 -8899,1514307967584,27 -8900,1514307989283,26 -8901,1514308084386,28 -8902,1514308179305,28 -8903,1514308221645,27 -8904,1514308295644,28 -8905,1514308477164,28 -8906,1514308703545,27 -8907,1514308789957,26 -8908,1514308828182,26 -8909,1514309013060,25 -8910,1514309145202,25 -8911,1514309249274,24 -8912,1514309357984,24 -8913,1514309403520,23 -8914,1514309429237,23 -8915,1514309458047,24 -8916,1514309506978,25 -8917,1514309587918,25 -8918,1514309661553,25 -8919,1514309781256,25 -8920,1514309870967,24 -8921,1514310039193,24 -8922,1514310165727,22 -8923,1514310321623,21 -8924,1514310465374,21 -8925,1514310542027,19 -8926,1514310557719,19 -8927,1514310647665,21 -8928,1514310732027,21 -8929,1514310773858,21 -8930,1514310808582,21 -8931,1514310996400,21 -8932,1514311309439,20 -8933,1514311478880,21 -8934,1514311520285,21 -8935,1514311600937,22 -8936,1514311708351,21 -8937,1514311768801,20 -8938,1514311820324,21 -8939,1514311878630,21 -8940,1514311939813,21 -8941,1514311977604,20 -8942,1514311996002,19 -8943,1514312026947,21 -8944,1514312188579,22 -8945,1514312334781,21 -8946,1514312418520,20 -8947,1514312486102,20 -8948,1514312511624,19 -8949,1514312609622,20 -8950,1514312732181,20 -8951,1514312871420,19 -8952,1514312978921,19 -8953,1514313059988,18 -8954,1514313150430,17 -8955,1514313194919,17 -8956,1514313248521,17 -8957,1514313335098,17 -8958,1514313410148,16 -8959,1514313439341,16 -8960,1514313480247,16 -8961,1514313536000,16 -8962,1514313590852,17 -8963,1514313634632,18 -8964,1514313692631,17 -8965,1514313806341,17 -8966,1514313893304,17 -8967,1514313924684,16 -8968,1514313980758,18 -8969,1514314028431,18 -8970,1514314093682,19 -8971,1514314157635,20 -8972,1514314176615,20 -8973,1514314202418,20 -8974,1514314344792,22 -8975,1514314505011,22 -8976,1514314542587,21 -8977,1514314574654,21 -8978,1514314619454,22 -8979,1514314660442,22 -8980,1514314682357,23 -8981,1514314766776,23 -8982,1514314804365,23 -8983,1514314816519,24 -8984,1514314869232,28 -8985,1514315000143,28 -8986,1514315090899,27 -8987,1514315146035,27 -8988,1514315230161,26 -8989,1514315381221,27 -8990,1514315537481,25 -8991,1514315605894,25 -8992,1514315653925,25 -8993,1514315699680,26 -8994,1514315864174,26 -8995,1514316083955,26 -8996,1514316219937,26 -8997,1514316302615,26 -8998,1514316392744,25 -8999,1514316505872,24 -9000,1514316567580,23 -9001,1514316625668,25 -9002,1514316679444,25 -9003,1514316734510,25 -9004,1514316832432,25 -9005,1514316889812,25 -9006,1514317031745,25 -9007,1514317086931,24 -9008,1514317176778,24 -9009,1514317268917,24 -9010,1514317322524,23 -9011,1514317373268,23 -9012,1514317401893,24 -9013,1514317430290,25 -9014,1514317572885,26 -9015,1514317759733,26 -9016,1514317863238,26 -9017,1514318006272,26 -9018,1514318106435,25 -9019,1514318196872,25 -9020,1514318349313,25 -9021,1514318473389,24 -9022,1514318557096,22 -9023,1514318598952,22 -9024,1514318637806,21 -9025,1514318689002,22 -9026,1514318846414,23 -9027,1514318992158,23 -9028,1514319004889,22 -9029,1514319072754,25 -9030,1514319224156,26 -9031,1514319328766,25 -9032,1514319372969,25 -9033,1514319408179,25 -9034,1514319566708,25 -9035,1514319642135,24 -9036,1514319703703,24 -9037,1514319787246,24 -9038,1514320004071,24 -9039,1514320266399,22 -9040,1514320366924,22 -9041,1514320405521,22 -9042,1514320466065,22 -9043,1514320560402,23 -9044,1514320736461,23 -9045,1514320902674,21 -9046,1514320941171,22 -9047,1514320962671,21 -9048,1514321035232,23 -9049,1514321111068,23 -9050,1514321135984,23 -9051,1514321202286,23 -9052,1514321295080,23 -9053,1514321366687,23 -9054,1514321510025,23 -9055,1514321704605,22 -9056,1514321801596,21 -9057,1514321832978,20 -9058,1514321962006,21 -9059,1514322091916,20 -9060,1514322130768,20 -9061,1514322168486,20 -9062,1514322205958,20 -9063,1514322238008,20 -9064,1514322328891,21 -9065,1514322420034,20 -9066,1514322441573,19 -9067,1514322460416,21 -9068,1514322518791,23 -9069,1514322609178,22 -9070,1514322664987,22 -9071,1514322734340,21 -9072,1514322797381,21 -9073,1514322852838,22 -9074,1514322936746,22 -9075,1514323018313,22 -9076,1514323092751,21 -9077,1514323143813,20 -9078,1514323182331,21 -9079,1514323276948,22 -9080,1514323357996,21 -9081,1514323373562,21 -9082,1514323394747,24 -9083,1514323412949,26 -9084,1514323496413,30 -9085,1514323600856,30 -9086,1514323639461,30 -9087,1514323875066,31 -9088,1514324283162,30 -9089,1514324479033,29 -9090,1514324797252,29 -9091,1514325094659,27 -9092,1514325297401,27 -9093,1514325483028,26 -9094,1514325534626,25 -9095,1514325583172,26 -9096,1514325615230,26 -9097,1514325662361,27 -9098,1514325777227,27 -9099,1514325877637,26 -9100,1514325944873,25 -9101,1514326006382,26 -9102,1514326039476,25 -9103,1514326073920,27 -9104,1514326128079,27 -9105,1514326220184,28 -9106,1514326350915,27 -9107,1514326459085,26 -9108,1514326516036,26 -9109,1514326557008,27 -9110,1514326642247,26 -9111,1514326715915,26 -9112,1514326877437,26 -9113,1514326996631,26 -9114,1514327040706,26 -9115,1514327124345,26 -9116,1514327331535,26 -9117,1514327482779,25 -9118,1514327526624,24 -9119,1514327637556,25 -9120,1514327924911,24 -9121,1514328149065,23 -9122,1514328170931,22 -9123,1514328192989,23 -9124,1514328358452,25 -9125,1514328538324,24 -9126,1514328637480,24 -9127,1514328710059,23 -9128,1514328798109,22 -9129,1514328927542,24 -9130,1514329037505,22 -9131,1514329073536,22 -9132,1514329099015,22 -9133,1514329127274,24 -9134,1514329175361,26 -9135,1514329255029,25 -9136,1514329372667,25 -9137,1514329485792,25 -9138,1514329570004,24 -9139,1514329640918,24 -9140,1514329686052,23 -9141,1514329737393,23 -9142,1514329801940,23 -9143,1514329995042,23 -9144,1514330160959,22 -9145,1514330176172,21 -9146,1514330204981,23 -9147,1514330240669,25 -9148,1514330331134,26 -9149,1514330448595,26 -9150,1514330610948,23 -9151,1514330781857,24 -9152,1514330918598,24 -9153,1514331046705,23 -9154,1514331164846,22 -9155,1514331245375,22 -9156,1514331302586,21 -9157,1514331363181,20 -9158,1514331559636,21 -9159,1514331825864,19 -9160,1514331945825,18 -9161,1514332015424,18 -9162,1514332076389,17 -9163,1514332124779,18 -9164,1514332189795,18 -9165,1514332263405,17 -9166,1514332315153,17 -9167,1514332368011,17 -9168,1514332412508,18 -9169,1514332460794,18 -9170,1514332495274,18 -9171,1514332553484,18 -9172,1514332638211,18 -9173,1514332708876,17 -9174,1514332750953,17 -9175,1514332798448,17 -9176,1514332810359,17 -9177,1514332864347,19 -9178,1514332909042,20 -9179,1514332967157,20 -9180,1514333011410,19 -9181,1514333034387,19 -9182,1514333062937,21 -9183,1514333143769,23 -9184,1514333238089,24 -9185,1514333334483,23 -9186,1514333479697,24 -9187,1514333637951,23 -9188,1514333759501,22 -9189,1514333862387,21 -9190,1514333932736,21 -9191,1514334003161,21 -9192,1514334093439,20 -9193,1514334164412,19 -9194,1514334303845,19 -9195,1514334433789,18 -9196,1514334497727,18 -9197,1514334603757,18 -9198,1514334708524,18 -9199,1514334766465,18 -9200,1514334830825,17 -9201,1514334891447,17 -9202,1514334920001,17 -9203,1514335011513,18 -9204,1514335023694,18 -9205,1514335116865,21 -9206,1514335236031,21 -9207,1514335272920,20 -9208,1514335291853,20 -9209,1514335346998,22 -9210,1514335452925,22 -9211,1514335583022,22 -9212,1514335722834,21 -9213,1514335834904,21 -9214,1514335922321,20 -9215,1514336045175,20 -9216,1514336193516,19 -9217,1514336297757,19 -9218,1514336345372,18 -9219,1514336387874,18 -9220,1514336477853,18 -9221,1514336557861,18 -9222,1514336619962,17 -9223,1514336667805,17 -9224,1514336732545,19 -9225,1514336839907,18 -9226,1514336923798,17 -9227,1514336935920,17 -9228,1514337059794,19 -9229,1514337195288,19 -9230,1514337231867,18 -9231,1514337256740,18 -9232,1514337307873,19 -9233,1514337361760,20 -9234,1514337383644,21 -9235,1514337477265,22 -9236,1514337572113,23 -9237,1514337594134,22 -9238,1514337612662,23 -9239,1514337647276,25 -9240,1514337714764,26 -9241,1514337835274,26 -9242,1514337932704,26 -9243,1514337994591,26 -9244,1514338191126,26 -9245,1514338366856,24 -9246,1514338444598,25 -9247,1514338772822,26 -9248,1514339053132,25 -9249,1514339128438,25 -9250,1514339199645,25 -9251,1514339238187,25 -9252,1514339283002,25 -9253,1514339351023,25 -9254,1514339409586,25 -9255,1514339480613,24 -9256,1514339544830,24 -9257,1514339589133,25 -9258,1514339627650,25 -9259,1514339690028,26 -9260,1514339741230,25 -9261,1514339750083,25 -9262,1514339897726,31 -9263,1514339919845,31 -9264,1514339989581,33 -9265,1514340053757,32 -9266,1514340201069,32 -9267,1514340358828,32 -9268,1514340488947,31 -9269,1514340654877,31 -9270,1514340726089,30 -9271,1514340814981,30 -9272,1514341001699,30 -9273,1514341263677,29 -9274,1514341445873,29 -9275,1514341497010,27 -9276,1514341543789,27 -9277,1514341595160,30 -9278,1514341660151,29 -9279,1514341725126,30 -9280,1514341915638,30 -9281,1514342097242,30 -9282,1514342125854,29 -9283,1514342220957,31 -9284,1514342335548,31 -9285,1514342459475,30 -9286,1514342572915,29 -9287,1514342623831,29 -9288,1514342662777,29 -9289,1514342700681,30 -9290,1514342862646,31 -9291,1514343056860,30 -9292,1514343113001,29 -9293,1514343187423,29 -9294,1514343278816,29 -9295,1514343314019,28 -9296,1514343363558,29 -9297,1514343420404,29 -9298,1514343598942,29 -9299,1514343851364,28 -9300,1514343961143,27 -9301,1514344010024,26 -9302,1514344060168,27 -9303,1514344191858,27 -9304,1514344384198,26 -9305,1514344568203,27 -9306,1514344701180,26 -9307,1514344729672,25 -9308,1514344748176,27 -9309,1514344763734,29 -9310,1514344803584,33 -9311,1514344851238,34 -9312,1514344931980,33 -9313,1514345116739,33 -9314,1514345242289,32 -9315,1514345352325,32 -9316,1514345642068,31 -9317,1514345957234,30 -9318,1514346176779,28 -9319,1514346358490,27 -9320,1514346492173,26 -9321,1514346590589,25 -9322,1514346654257,25 -9323,1514346755810,24 -9324,1514346848092,24 -9325,1514346856856,23 -9326,1514346902500,27 -9327,1514346967931,28 -9328,1514347084818,30 -9329,1514347200212,28 -9330,1514347267872,27 -9331,1514347471650,27 -9332,1514347660402,27 -9333,1514347747016,26 -9334,1514347834906,26 -9335,1514347925099,25 -9336,1514348000296,25 -9337,1514348061052,24 -9338,1514348109395,24 -9339,1514348159794,26 -9340,1514348197660,26 -9341,1514348237721,27 -9342,1514348253237,28 -9343,1514348416645,30 -9344,1514348664659,29 -9345,1514348758339,28 -9346,1514348839437,28 -9347,1514348948635,27 -9348,1514349058822,26 -9349,1514349133534,25 -9350,1514349196002,24 -9351,1514349290570,24 -9352,1514349363313,24 -9353,1514349416769,23 -9354,1514349504989,23 -9355,1514349743487,23 -9356,1514349937595,22 -9357,1514350089352,21 -9358,1514350229620,21 -9359,1514350319931,20 -9360,1514350542077,19 -9361,1514350766854,18 -9362,1514350847294,21 -9363,1514350930581,20 -9364,1514351021437,21 -9365,1514351056261,21 -9366,1514351088290,21 -9367,1514351143275,22 -9368,1514351305519,22 -9369,1514351480856,21 -9370,1514351534653,20 -9371,1514351569044,19 -9372,1514351605299,20 -9373,1514351646443,20 -9374,1514351670876,20 -9375,1514351731362,20 -9376,1514351759693,20 -9377,1514351801024,22 -9378,1514351861767,22 -9379,1514351909669,22 -9380,1514351997127,21 -9381,1514352073416,21 -9382,1514352275300,21 -9383,1514352444742,20 -9384,1514352515601,20 -9385,1514352572959,19 -9386,1514352688808,19 -9387,1514352826167,18 -9388,1514352923189,18 -9389,1514352987126,18 -9390,1514353027795,17 -9391,1514353201907,18 -9392,1514353239646,16 -9393,1514353287379,16 -9394,1514353313722,17 -9395,1514353364242,17 -9396,1514353447566,18 -9397,1514353489888,17 -9398,1514353548851,17 -9399,1514353583331,17 -9400,1514353663808,17 -9401,1514353730682,16 -9402,1514353759163,16 -9403,1514353920448,17 -9404,1514354008967,16 -9405,1514354097017,15 -9406,1514354116884,14 -9407,1514354129856,15 -9408,1514354158479,17 -9409,1514354243138,18 -9410,1514354315295,20 -9411,1514354327292,20 -9412,1514354335915,24 -9413,1514354614055,29 -9414,1514354651948,29 -9415,1514354677959,29 -9416,1514354726244,31 -9417,1514354832358,31 -9418,1514354967964,31 -9419,1514355038211,29 -9420,1514355083382,29 -9421,1514355173932,30 -9422,1514355389760,29 -9423,1514355596982,29 -9424,1514355719055,28 -9425,1514355793404,27 -9426,1514355855506,29 -9427,1514355923201,30 -9428,1514356004612,30 -9429,1514356157613,29 -9430,1514356257051,29 -9431,1514356308353,29 -9432,1514356432589,29 -9433,1514356591318,28 -9434,1514356772324,28 -9435,1514356908596,27 -9436,1514356944195,26 -9437,1514357060215,27 -9438,1514357237245,26 -9439,1514357382030,26 -9440,1514357423444,25 -9441,1514357458860,26 -9442,1514357522584,27 -9443,1514357544519,29 -9444,1514357590236,31 -9445,1514357652500,32 -9446,1514357699641,31 -9447,1514357757153,32 -9448,1514357867959,32 -9449,1514357981981,32 -9450,1514358039788,32 -9451,1514358075410,32 -9452,1514358172869,33 -9453,1514358314136,33 -9454,1514358387871,32 -9455,1514358419909,32 -9456,1514358461039,33 -9457,1514358486386,34 -9458,1514358528499,35 -9459,1514358567131,36 -9460,1514358593860,37 -9461,1514358619197,38 -9462,1514358679224,40 -9463,1514358768955,41 -9464,1514358942625,40 -9465,1514359178154,40 -9466,1514359295838,38 -9467,1514359338729,38 -9468,1514359399869,39 -9469,1514359445053,39 -9470,1514359518286,40 -9471,1514359613438,40 -9472,1514359792308,39 -9473,1514359959167,38 -9474,1514360003863,38 -9475,1514360124261,39 -9476,1514360315628,39 -9477,1514360490950,38 -9478,1514360597942,38 -9479,1514360632560,37 -9480,1514360681345,39 -9481,1514360722177,40 -9482,1514360779650,40 -9483,1514360860345,39 -9484,1514360908637,39 -9485,1514360998741,39 -9486,1514361121638,39 -9487,1514361186076,38 -9488,1514361231296,38 -9489,1514361258987,39 -9490,1514361536856,41 -9491,1514361717230,39 -9492,1514361843939,38 -9493,1514361996778,37 -9494,1514362129347,36 -9495,1514362305712,35 -9496,1514362426237,34 -9497,1514362451473,33 -9498,1514362515287,35 -9499,1514362577338,34 -9500,1514362699008,35 -9501,1514362768306,34 -9502,1514362826697,33 -9503,1514363114859,33 -9504,1514363434072,32 -9505,1514363508999,30 -9506,1514363553383,29 -9507,1514363668625,29 -9508,1514363817983,30 -9509,1514363931213,29 -9510,1514363994735,27 -9511,1514364103139,27 -9512,1514364420924,27 -9513,1514364675565,29 -9514,1514364790325,28 -9515,1514364980971,28 -9516,1514365107773,28 -9517,1514365417177,27 -9518,1514365756330,26 -9519,1514365834907,24 -9520,1514365874023,24 -9521,1514365925641,25 -9522,1514365966929,25 -9523,1514366078511,24 -9524,1514366246632,24 -9525,1514366372848,22 -9526,1514366436882,21 -9527,1514366501360,21 -9528,1514366536993,21 -9529,1514366605697,21 -9530,1514366779524,20 -9531,1514367062106,19 -9532,1514367221510,18 -9533,1514367262944,17 -9534,1514367346127,17 -9535,1514367423360,15 -9536,1514367477477,14 -9537,1514367542299,14 -9538,1514367577028,13 -9539,1514367631829,12 -9540,1514367683074,11 -9541,1514367691930,11 -9542,1514367760190,13 -9543,1514367775415,12 -9544,1514367797551,14 -9545,1514367848695,15 -9546,1514367962377,15 -9547,1514368086453,14 -9548,1514368139507,13 -9549,1514368161256,12 -9550,1514368182564,12 -9551,1514368233950,13 -9552,1514368288885,13 -9553,1514368308418,12 -9554,1514368330049,12 -9555,1514368357795,12 -9556,1514368405682,13 -9557,1514368507048,13 -9558,1514368577895,14 -9559,1514368641632,13 -9560,1514368710426,13 -9561,1514368728970,14 -9562,1514368773681,17 -9563,1514368847904,16 -9564,1514368915547,16 -9565,1514369026129,16 -9566,1514369172231,15 -9567,1514369265676,14 -9568,1514369326552,14 -9569,1514369404643,14 -9570,1514369493838,13 -9571,1514369556275,14 -9572,1514369620773,13 -9573,1514369730785,13 -9574,1514369901319,12 -9575,1514370002096,12 -9576,1514370036523,11 -9577,1514370080964,11 -9578,1514370105892,10 -9579,1514370193817,11 -9580,1514370271058,11 -9581,1514370302535,11 -9582,1514370377790,11 -9583,1514370428718,12 -9584,1514370506753,12 -9585,1514370594685,11 -9586,1514370655035,11 -9587,1514370714027,12 -9588,1514370751916,11 -9589,1514370783842,12 -9590,1514370802843,14 -9591,1514370817555,14 -9592,1514370830569,16 -9593,1514370842709,18 -9594,1514370861359,21 -9595,1514370876643,23 -9596,1514370921967,25 -9597,1514370966388,25 -9598,1514371002193,27 -9599,1514371042855,29 -9600,1514371116579,29 -9601,1514371236568,29 -9602,1514371345487,30 -9603,1514371454582,30 -9604,1514371550997,29 -9605,1514371591805,29 -9606,1514371619927,29 -9607,1514371734720,31 -9608,1514372012393,30 -9609,1514372223712,30 -9610,1514372297900,30 -9611,1514372350165,29 -9612,1514372594711,30 -9613,1514372846544,29 -9614,1514372894485,28 -9615,1514372935766,29 -9616,1514372973880,29 -9617,1514373009267,30 -9618,1514373106078,30 -9619,1514373201251,30 -9620,1514373253026,29 -9621,1514373336583,30 -9622,1514373521620,31 -9623,1514373727094,31 -9624,1514373828854,30 -9625,1514373894278,29 -9626,1514373984594,29 -9627,1514374098665,28 -9628,1514374166532,28 -9629,1514374313518,29 -9630,1514374623994,29 -9631,1514374867122,27 -9632,1514374948216,27 -9633,1514374986231,26 -9634,1514375013959,27 -9635,1514375102623,28 -9636,1514375186532,27 -9637,1514375347009,27 -9638,1514375531031,26 -9639,1514375568446,26 -9640,1514375622338,26 -9641,1514375676813,26 -9642,1514375692039,28 -9643,1514375752340,30 -9644,1514375814700,31 -9645,1514375835639,31 -9646,1514375923023,34 -9647,1514376007253,33 -9648,1514376094201,34 -9649,1514376215857,33 -9650,1514376280490,33 -9651,1514376318740,33 -9652,1514376376527,33 -9653,1514376421233,34 -9654,1514376502360,35 -9655,1514376627848,35 -9656,1514376748319,35 -9657,1514376822051,35 -9658,1514376960711,34 -9659,1514377233807,33 -9660,1514377490642,32 -9661,1514377661734,31 -9662,1514377775782,31 -9663,1514377830266,30 -9664,1514377857721,30 -9665,1514378040023,33 -9666,1514378104159,31 -9667,1514378152866,30 -9668,1514378193880,31 -9669,1514378271675,31 -9670,1514378338424,31 -9671,1514378441671,31 -9672,1514378518337,29 -9673,1514378543174,29 -9674,1514378600485,31 -9675,1514378661672,30 -9676,1514378696170,29 -9677,1514378718833,31 -9678,1514378770240,33 -9679,1514378834858,33 -9680,1514378866784,32 -9681,1514378900994,33 -9682,1514378981291,34 -9683,1514379146226,33 -9684,1514379283432,32 -9685,1514379387248,31 -9686,1514379512989,30 -9687,1514379581617,29 -9688,1514379619657,28 -9689,1514379657863,28 -9690,1514379693830,29 -9691,1514379754752,30 -9692,1514379868367,30 -9693,1514379989223,29 -9694,1514380043626,31 -9695,1514380205239,32 -9696,1514380567870,33 -9697,1514380795313,32 -9698,1514380854707,31 -9699,1514380909230,32 -9700,1514380924795,32 -9701,1514381112822,36 -9702,1514381286909,35 -9703,1514381377104,34 -9704,1514381448276,33 -9705,1514381500172,33 -9706,1514381539255,33 -9707,1514381570859,35 -9708,1514381586103,36 -9709,1514381668711,40 -9710,1514381809809,40 -9711,1514381910386,39 -9712,1514382090722,39 -9713,1514382274213,37 -9714,1514382413703,36 -9715,1514382555608,36 -9716,1514382594572,36 -9717,1514382715403,37 -9718,1514382765548,36 -9719,1514382780309,37 -9720,1514382808910,41 -9721,1514382867060,44 -9722,1514383009843,44 -9723,1514383165690,43 -9724,1514383247268,42 -9725,1514383348351,41 -9726,1514383388904,41 -9727,1514383493385,41 -9728,1514383638700,41 -9729,1514383711840,40 -9730,1514383886501,39 -9731,1514384160926,38 -9732,1514384194215,37 -9733,1514384290653,37 -9734,1514384338202,37 -9735,1514384389351,38 -9736,1514384438023,38 -9737,1514384507431,38 -9738,1514384515284,38 -9739,1514384530536,48 -9740,1514384542207,53 -9741,1514384712354,63 -9742,1514384897673,62 -9743,1514384967820,62 -9744,1514385242726,63 -9745,1514385353218,61 -9746,1514385578546,62 -9747,1514385800605,60 -9748,1514386152534,59 -9749,1514386417520,58 -9750,1514386504104,56 -9751,1514386637201,56 -9752,1514386727278,56 -9753,1514386892098,55 -9754,1514387256186,55 -9755,1514387629335,53 -9756,1514387673605,52 -9757,1514387709570,52 -9758,1514387770556,54 -9759,1514387864938,54 -9760,1514388007078,53 -9761,1514388113027,52 -9762,1514388240411,50 -9763,1514388724365,50 -9764,1514388847458,48 -9765,1514388897468,48 -9766,1514388975011,48 -9767,1514389109315,47 -9768,1514389166222,46 -9769,1514389640297,47 -9770,1514389681558,45 -9771,1514389841880,45 -9772,1514389900751,45 -9773,1514390005588,44 -9774,1514390156507,44 -9775,1514390387703,43 -9776,1514390518053,42 -9777,1514390723401,41 -9778,1514390946896,41 -9779,1514391029999,40 -9780,1514391058127,38 -9781,1514391080082,41 -9782,1514391150059,45 -9783,1514391259211,44 -9784,1514391344783,42 -9785,1514391472252,41 -9786,1514391553487,39 -9787,1514391622530,40 -9788,1514391838320,39 -9789,1514391872464,37 -9790,1514391953768,39 -9791,1514392153066,38 -9792,1514392267196,37 -9793,1514392313037,35 -9794,1514392380067,35 -9795,1514392486284,35 -9796,1514392616399,33 -9797,1514392693545,32 -9798,1514392742538,31 -9799,1514392790665,30 -9800,1514392828517,30 -9801,1514392847113,32 -9802,1514392909000,33 -9803,1514393013448,33 -9804,1514393198042,32 -9805,1514393346109,30 -9806,1514393498327,29 -9807,1514393666074,28 -9808,1514393783739,27 -9809,1514394048026,28 -9810,1514394310271,26 -9811,1514394486139,25 -9812,1514394588809,23 -9813,1514394634769,22 -9814,1514394674369,21 -9815,1514394832158,20 -9816,1514395010361,19 -9817,1514395074537,17 -9818,1514395120158,16 -9819,1514395159889,15 -9820,1514395205434,17 -9821,1514395233919,17 -9822,1514395282731,18 -9823,1514395328288,17 -9824,1514395342971,16 -9825,1514395358790,17 -9826,1514395374280,19 -9827,1514395411575,20 -9828,1514395498816,20 -9829,1514395602938,18 -9830,1514395691584,17 -9831,1514395740083,15 -9832,1514395778331,15 -9833,1514395811144,15 -9834,1514395826481,14 -9835,1514395911650,15 -9836,1514395953543,13 -9837,1514396030669,14 -9838,1514396108684,12 -9839,1514396128066,17 -9840,1514396141179,20 -9841,1514396168682,28 -9842,1514396228769,29 -9843,1514396291706,29 -9844,1514396325635,28 -9845,1514396393254,29 -9846,1514396460348,29 -9847,1514396496200,29 -9848,1514396604765,30 -9849,1514396734914,28 -9850,1514396816030,28 -9851,1514396903808,27 -9852,1514396983930,27 -9853,1514397032868,27 -9854,1514397061605,26 -9855,1514397099853,27 -9856,1514397148411,27 -9857,1514397189327,28 -9858,1514397275614,30 -9859,1514397387348,29 -9860,1514397440093,28 -9861,1514397481751,29 -9862,1514397577384,30 -9863,1514397664533,29 -9864,1514397758326,28 -9865,1514397904705,27 -9866,1514398050422,27 -9867,1514398207013,26 -9868,1514398374748,26 -9869,1514398471980,25 -9870,1514398549077,24 -9871,1514398638232,25 -9872,1514398691521,24 -9873,1514398766326,25 -9874,1514398821781,24 -9875,1514398880184,23 -9876,1514398938887,23 -9877,1514398980172,22 -9878,1514399066947,22 -9879,1514399134381,22 -9880,1514399172728,21 -9881,1514399198223,22 -9882,1514399209873,25 -9883,1514399258750,30 -9884,1514399330478,30 -9885,1514399361013,30 -9886,1514399558629,31 -9887,1514399757711,30 -9888,1514399875897,29 -9889,1514400009529,29 -9890,1514400136117,29 -9891,1514400210708,28 -9892,1514400391897,28 -9893,1514400595615,27 -9894,1514400639834,27 -9895,1514400690597,27 -9896,1514400702541,27 -9897,1514400792797,30 -9898,1514400896952,31 -9899,1514400991298,30 -9900,1514401064948,29 -9901,1514401080285,30 -9902,1514401131708,36 -9903,1514401289051,35 -9904,1514401418842,35 -9905,1514401450447,34 -9906,1514401633400,35 -9907,1514401819486,35 -9908,1514401889596,33 -9909,1514401982200,33 -9910,1514402052617,32 -9911,1514402119272,32 -9912,1514402216755,31 -9913,1514402311790,30 -9914,1514402352901,30 -9915,1514402449539,30 -9916,1514402552716,29 -9917,1514402594473,29 -9918,1514402642584,29 -9919,1514402769587,29 -9920,1514402926187,29 -9921,1514403019488,27 -9922,1514403076784,27 -9923,1514403268085,27 -9924,1514403462399,25 -9925,1514403507027,25 -9926,1514403539413,26 -9927,1514403661096,27 -9928,1514403780392,28 -9929,1514403930756,27 -9930,1514404080216,26 -9931,1514404118338,24 -9932,1514404179105,25 -9933,1514404221788,25 -9934,1514404256899,25 -9935,1514404282763,26 -9936,1514404401336,27 -9937,1514404517673,26 -9938,1514404611908,25 -9939,1514404624222,24 -9940,1514404659044,28 -9941,1514404680904,30 -9942,1514405028407,33 -9943,1514405143405,31 -9944,1514405234650,31 -9945,1514405372131,32 -9946,1514405512820,30 -9947,1514405583526,30 -9948,1514405618204,30 -9949,1514405738648,31 -9950,1514405848280,30 -9951,1514405915640,29 -9952,1514405947819,29 -9953,1514406086722,30 -9954,1514406257966,29 -9955,1514406313463,29 -9956,1514406344591,29 -9957,1514406380858,31 -9958,1514406448154,32 -9959,1514406564787,32 -9960,1514406649088,31 -9961,1514406707348,31 -9962,1514406765549,31 -9963,1514406784228,31 -9964,1514406881675,34 -9965,1514407033267,33 -9966,1514407150526,32 -9967,1514407230476,32 -9968,1514407355148,31 -9969,1514407478781,30 -9970,1514407673795,29 -9971,1514407806644,27 -9972,1514407869658,27 -9973,1514407982817,27 -9974,1514408082403,26 -9975,1514408175545,25 -9976,1514408275825,24 -9977,1514408350941,24 -9978,1514408438362,23 -9979,1514408538444,22 -9980,1514408682794,21 -9981,1514408801587,21 -9982,1514408830316,20 -9983,1514408845553,24 -9984,1514408886819,26 -9985,1514408932150,26 -9986,1514408982829,28 -9987,1514409046577,27 -9988,1514409091363,26 -9989,1514409122360,26 -9990,1514409203316,27 -9991,1514409281285,27 -9992,1514409472510,26 -9993,1514409730612,25 -9994,1514409852381,23 -9995,1514409943516,23 -9996,1514410034656,22 -9997,1514410070174,24 -9998,1514410159878,24 -9999,1514410247246,23 -10000,1514410276121,23 -10001,1514410304182,23 -10002,1514410434830,27 -10003,1514410542793,27 -10004,1514410719931,25 -10005,1514410836146,24 -10006,1514410931825,25 -10007,1514410950819,24 -10008,1514410974277,26 -10009,1514411015579,27 -10010,1514411094459,27 -10011,1514411163992,28 -10012,1514411227989,28 -10013,1514411354201,26 -10014,1514411441178,26 -10015,1514411482349,26 -10016,1514411540138,27 -10017,1514411702553,27 -10018,1514411890592,26 -10019,1514411960835,25 -10020,1514411988857,25 -10021,1514412014064,25 -10022,1514412033445,27 -10023,1514412064886,29 -10024,1514412155452,29 -10025,1514412222227,28 -10026,1514412313244,29 -10027,1514412610368,29 -10028,1514412851337,28 -10029,1514412909010,26 -10030,1514412931554,26 -10031,1514412972708,27 -10032,1514413033206,27 -10033,1514413090260,27 -10034,1514413177034,27 -10035,1514413413792,27 -10036,1514413616567,27 -10037,1514413727560,26 -10038,1514413829585,26 -10039,1514413993888,24 -10040,1514414199823,25 -10041,1514414312258,25 -10042,1514414411089,26 -10043,1514414482124,25 -10044,1514414526694,25 -10045,1514414565235,25 -10046,1514414650063,25 -10047,1514414733411,24 -10048,1514414808535,24 -10049,1514414909320,24 -10050,1514414972861,24 -10051,1514415046331,24 -10052,1514415144918,23 -10053,1514415224558,23 -10054,1514415282238,23 -10055,1514415310837,22 -10056,1514415325700,22 -10057,1514415348243,26 -10058,1514415424957,28 -10059,1514415554317,28 -10060,1514415655675,28 -10061,1514415703786,26 -10062,1514415725000,27 -10063,1514415747569,29 -10064,1514415862785,32 -10065,1514416031690,32 -10066,1514416165529,31 -10067,1514416242073,30 -10068,1514416393029,30 -10069,1514416567231,29 -10070,1514416638503,28 -10071,1514416697916,28 -10072,1514416735639,28 -10073,1514416778851,29 -10074,1514416900977,29 -10075,1514417062673,27 -10076,1514417309881,27 -10077,1514417522793,26 -10078,1514417781416,25 -10079,1514418033924,24 -10080,1514418077859,22 -10081,1514418117217,22 -10082,1514418244116,23 -10083,1514418497608,22 -10084,1514418648972,22 -10085,1514418723514,22 -10086,1514418808086,22 -10087,1514418879992,22 -10088,1514418957318,21 -10089,1514419054773,21 -10090,1514419188242,22 -10091,1514419317797,21 -10092,1514419369819,20 -10093,1514419441904,20 -10094,1514419548553,19 -10095,1514419656502,18 -10096,1514419744525,17 -10097,1514419802400,17 -10098,1514419863523,16 -10099,1514419936464,16 -10100,1514420034580,15 -10101,1514420154046,15 -10102,1514420219362,15 -10103,1514420303601,15 -10104,1514420420247,14 -10105,1514420465950,13 -10106,1514420599120,13 -10107,1514420677012,11 -10108,1514420719586,12 -10109,1514420756913,12 -10110,1514420791720,13 -10111,1514420817174,13 -10112,1514420842657,13 -10113,1514420861446,14 -10114,1514420870280,14 -10115,1514420885540,17 -10116,1514421035188,19 -10117,1514421224653,18 -10118,1514421298348,17 -10119,1514421340360,17 -10120,1514421369325,17 -10121,1514421385743,17 -10122,1514421475954,20 -10123,1514421491344,21 -10124,1514421516287,23 -10125,1514421583908,25 -10126,1514421691856,25 -10127,1514421749733,25 -10128,1514421797138,24 -10129,1514421844155,25 -10130,1514421872699,25 -10131,1514421903977,26 -10132,1514421922518,28 -10133,1514421940521,30 -10134,1514421965157,34 -10135,1514422036799,36 -10136,1514422197143,36 -10137,1514422359167,35 -10138,1514422430430,35 -10139,1514422475932,34 -10140,1514422513704,34 -10141,1514422551452,35 -10142,1514422620782,36 -10143,1514422705306,36 -10144,1514422779720,36 -10145,1514422956073,36 -10146,1514423132924,35 -10147,1514423160728,35 -10148,1514423250709,36 -10149,1514423288160,36 -10150,1514423770276,37 -10151,1514424257263,36 -10152,1514424501305,34 -10153,1514424578717,34 -10154,1514424683868,34 -10155,1514424807113,33 -10156,1514424891499,33 -10157,1514424972315,34 -10158,1514425092659,34 -10159,1514425224850,35 -10160,1514425320785,34 -10161,1514425362203,33 -10162,1514425383542,34 -10163,1514425405280,38 -10164,1514425553333,42 -10165,1514425891557,42 -10166,1514426159550,40 -10167,1514426310290,39 -10168,1514426397802,39 -10169,1514426417531,39 -10170,1514426503579,42 -10171,1514426597195,42 -10172,1514426779020,42 -10173,1514426958422,41 -10174,1514427048322,41 -10175,1514427142603,41 -10176,1514427222463,40 -10177,1514427388216,40 -10178,1514427497270,39 -10179,1514427679708,39 -10180,1514427943569,37 -10181,1514428195597,36 -10182,1514428207734,36 -10183,1514428334742,41 -10184,1514428474200,40 -10185,1514428558913,40 -10186,1514428635550,40 -10187,1514428673095,39 -10188,1514428704029,40 -10189,1514428751239,42 -10190,1514428884137,43 -10191,1514429069941,41 -10192,1514429196736,40 -10193,1514429270630,39 -10194,1514429345795,39 -10195,1514429413085,38 -10196,1514429549650,38 -10197,1514429778765,37 -10198,1514430113569,36 -10199,1514430381925,34 -10200,1514430450067,33 -10201,1514430543923,33 -10202,1514430652431,32 -10203,1514430696649,30 -10204,1514430833491,30 -10205,1514430975477,29 -10206,1514431014937,28 -10207,1514431033450,28 -10208,1514431068068,29 -10209,1514431103117,29 -10210,1514431125511,30 -10211,1514431216220,31 -10212,1514431324528,31 -10213,1514431359848,30 -10214,1514431421785,31 -10215,1514431465626,32 -10216,1514431536469,32 -10217,1514431600829,32 -10218,1514431626718,31 -10219,1514431664315,33 -10220,1514431793381,33 -10221,1514431955312,32 -10222,1514432168525,32 -10223,1514432377262,30 -10224,1514432502464,30 -10225,1514432588779,29 -10226,1514432627040,29 -10227,1514432672718,29 -10228,1514432707279,29 -10229,1514432722419,29 -10230,1514432763239,33 -10231,1514432867516,33 -10232,1514432955392,33 -10233,1514433027028,34 -10234,1514433100985,35 -10235,1514433175689,36 -10236,1514433232884,36 -10237,1514433339095,36 -10238,1514433594866,34 -10239,1514433805190,33 -10240,1514433852886,33 -10241,1514433874473,34 -10242,1514433929539,36 -10243,1514433980867,37 -10244,1514434058966,37 -10245,1514434199380,37 -10246,1514434327530,36 -10247,1514434385524,35 -10248,1514434437633,35 -10249,1514434487185,36 -10250,1514434610810,36 -10251,1514434717206,36 -10252,1514434791427,34 -10253,1514434920453,34 -10254,1514434987409,33 -10255,1514435005852,32 -10256,1514435102706,35 -10257,1514435233755,34 -10258,1514435331821,33 -10259,1514435545742,32 -10260,1514435894500,31 -10261,1514436086276,30 -10262,1514436134920,29 -10263,1514436205824,30 -10264,1514436241575,31 -10265,1514436272597,31 -10266,1514436321497,32 -10267,1514436520877,32 -10268,1514436772934,30 -10269,1514436856756,30 -10270,1514436921368,31 -10271,1514436989127,30 -10272,1514437021079,31 -10273,1514437127509,31 -10274,1514437220803,30 -10275,1514437396183,29 -10276,1514437607787,28 -10277,1514437773916,27 -10278,1514437845120,26 -10279,1514437914058,25 -10280,1514437992835,25 -10281,1514438177094,24 -10282,1514438373355,22 -10283,1514438489036,24 -10284,1514438608142,23 -10285,1514438680199,22 -10286,1514438735204,22 -10287,1514438880731,22 -10288,1514438994979,22 -10289,1514439009906,22 -10290,1514439096931,24 -10291,1514439160543,24 -10292,1514439178860,23 -10293,1514439197313,24 -10294,1514439264373,26 -10295,1514439422493,26 -10296,1514439519755,26 -10297,1514439538007,25 -10298,1514439592843,26 -10299,1514439667680,26 -10300,1514439827249,25 -10301,1514439970072,24 -10302,1514440008544,23 -10303,1514440078781,23 -10304,1514440133055,23 -10305,1514440197474,22 -10306,1514440288905,22 -10307,1514440391492,21 -10308,1514440468349,21 -10309,1514440484012,21 -10310,1514440499195,23 -10311,1514440550783,27 -10312,1514440598252,27 -10313,1514440642916,26 -10314,1514440685195,28 -10315,1514440913716,28 -10316,1514441136262,27 -10317,1514441187898,27 -10318,1514441212270,26 -10319,1514441250992,29 -10320,1514441318960,30 -10321,1514441367153,28 -10322,1514441505126,29 -10323,1514441537088,28 -10324,1514441592250,29 -10325,1514441614375,28 -10326,1514441633905,29 -10327,1514441655326,32 -10328,1514441870992,35 -10329,1514442079709,34 -10330,1514442223940,35 -10331,1514442284663,35 -10332,1514442355880,35 -10333,1514442475994,35 -10334,1514442585138,34 -10335,1514442669793,33 -10336,1514442770219,33 -10337,1514442923025,33 -10338,1514443058287,32 -10339,1514443336396,31 -10340,1514443679979,29 -10341,1514443769007,29 -10342,1514443800174,30 -10343,1514443922892,32 -10344,1514444077528,31 -10345,1514444164592,30 -10346,1514444315182,29 -10347,1514444503289,29 -10348,1514444613085,28 -10349,1514444727314,27 -10350,1514444846377,28 -10351,1514444917474,27 -10352,1514445058125,26 -10353,1514445217889,25 -10354,1514445364446,25 -10355,1514445488205,25 -10356,1514445565414,25 -10357,1514445646417,25 -10358,1514445704111,25 -10359,1514445735914,24 -10360,1514445758674,24 -10361,1514445832793,26 -10362,1514445923882,25 -10363,1514445978769,24 -10364,1514446097829,24 -10365,1514446242009,24 -10366,1514446339702,24 -10367,1514446412972,24 -10368,1514446444363,23 -10369,1514446489991,24 -10370,1514446620249,24 -10371,1514446721393,23 -10372,1514446749976,23 -10373,1514446827273,24 -10374,1514446907495,24 -10375,1514447004359,24 -10376,1514447121180,22 -10377,1514447249024,22 -10378,1514447367457,21 -10379,1514447412169,20 -10380,1514447431038,20 -10381,1514447494986,21 -10382,1514447563618,20 -10383,1514447595606,20 -10384,1514447617857,19 -10385,1514447635750,20 -10386,1514447713882,21 -10387,1514447872799,21 -10388,1514448009024,20 -10389,1514448130977,19 -10390,1514448215406,19 -10391,1514448253451,19 -10392,1514448321048,19 -10393,1514448362940,19 -10394,1514448436762,20 -10395,1514448512499,19 -10396,1514448527362,19 -10397,1514448588573,21 -10398,1514448665260,21 -10399,1514448712931,21 -10400,1514448876780,21 -10401,1514449025094,20 -10402,1514449070838,19 -10403,1514449115647,19 -10404,1514449134549,19 -10405,1514449205506,20 -10406,1514449285085,19 -10407,1514449319995,19 -10408,1514449390758,19 -10409,1514449573357,19 -10410,1514449741780,18 -10411,1514449789108,19 -10412,1514449804568,19 -10413,1514449831474,22 -10414,1514449889396,23 -10415,1514449983288,23 -10416,1514450057645,22 -10417,1514450141332,21 -10418,1514450209251,21 -10419,1514450230804,22 -10420,1514450272250,24 -10421,1514450313844,23 -10422,1514450406748,25 -10423,1514450492504,24 -10424,1514450521183,24 -10425,1514450571870,25 -10426,1514450711696,27 -10427,1514450835017,28 -10428,1514450864577,28 -10429,1514450911740,29 -10430,1514450962546,29 -10431,1514451013240,30 -10432,1514451080670,31 -10433,1514451217248,30 -10434,1514451346860,30 -10435,1514451375038,29 -10436,1514451471844,31 -10437,1514451568359,31 -10438,1514451600347,30 -10439,1514451686878,31 -10440,1514451807296,30 -10441,1514451950265,30 -10442,1514451998647,30 -10443,1514452081509,31 -10444,1514452138537,31 -10445,1514452174220,30 -10446,1514452193008,31 -10447,1514452726308,34 -10448,1514453254980,33 -10449,1514453371340,31 -10450,1514453506281,30 -10451,1514453611298,30 -10452,1514453686485,30 -10453,1514453718135,29 -10454,1514453759287,30 -10455,1514453856176,30 -10456,1514453973982,29 -10457,1514454064836,29 -10458,1514454168702,29 -10459,1514454262200,29 -10460,1514454336545,28 -10461,1514454390620,29 -10462,1514454571184,29 -10463,1514454748788,28 -10464,1514454819592,28 -10465,1514454870305,27 -10466,1514454918569,27 -10467,1514454956385,28 -10468,1514454988604,27 -10469,1514455010335,29 -10470,1514455165220,31 -10471,1514455326708,30 -10472,1514455460684,29 -10473,1514455692631,30 -10474,1514455841401,28 -10475,1514455862566,28 -10476,1514455898091,29 -10477,1514455986191,29 -10478,1514456083096,29 -10479,1514456199009,28 -10480,1514456314564,28 -10481,1514456372643,28 -10482,1514456407043,28 -10483,1514456494749,28 -10484,1514456525706,28 -10485,1514456577488,30 -10486,1514456668046,31 -10487,1514456823073,31 -10488,1514456992998,30 -10489,1514457125697,28 -10490,1514457219918,27 -10491,1514457364592,27 -10492,1514457508878,26 -10493,1514457537318,26 -10494,1514457586661,27 -10495,1514457686001,27 -10496,1514457796045,25 -10497,1514457842969,26 -10498,1514457887325,27 -10499,1514457908941,27 -10500,1514457947224,29 -10501,1514458036875,29 -10502,1514458113699,26 -10503,1514458185392,28 -10504,1514458250607,28 -10505,1514458325636,28 -10506,1514458395113,27 -10507,1514458516309,27 -10508,1514458692012,26 -10509,1514458769045,25 -10510,1514458869208,24 -10511,1514458960053,23 -10512,1514458991027,23 -10513,1514459049006,25 -10514,1514459099971,25 -10515,1514459162122,25 -10516,1514459217066,25 -10517,1514459304344,25 -10518,1514459474435,23 -10519,1514459601655,23 -10520,1514459647906,23 -10521,1514459708885,23 -10522,1514459773966,23 -10523,1514459832731,23 -10524,1514459942675,22 -10525,1514460061557,22 -10526,1514460152634,21 -10527,1514460232094,21 -10528,1514460320057,20 -10529,1514460458919,21 -10530,1514460654729,20 -10531,1514460786943,19 -10532,1514460844812,19 -10533,1514460914237,19 -10534,1514460979203,18 -10535,1514461028154,17 -10536,1514461069563,18 -10537,1514461121645,18 -10538,1514461162932,17 -10539,1514461200576,18 -10540,1514461235543,18 -10541,1514461257599,18 -10542,1514461299670,19 -10543,1514461338239,19 -10544,1514461360700,20 -10545,1514461441405,21 -10546,1514461538085,20 -10547,1514461642581,22 -10548,1514461791128,21 -10549,1514461864886,20 -10550,1514461927183,20 -10551,1514462015946,19 -10552,1514462146250,19 -10553,1514462239416,18 -10554,1514462305716,18 -10555,1514462409405,18 -10556,1514462488155,17 -10557,1514462528085,17 -10558,1514462556322,17 -10559,1514462595615,17 -10560,1514462633873,17 -10561,1514462695485,17 -10562,1514462746944,18 -10563,1514462785448,17 -10564,1514462817459,16 -10565,1514462849361,17 -10566,1514462900685,18 -10567,1514462974815,17 -10568,1514463039499,17 -10569,1514463077337,18 -10570,1514463155156,19 -10571,1514463236050,18 -10572,1514463302852,18 -10573,1514463472561,18 -10574,1514463593842,17 -10575,1514463674688,15 -10576,1514463785107,16 -10577,1514463876313,16 -10578,1514463950465,16 -10579,1514464014276,15 -10580,1514464069505,15 -10581,1514464108364,15 -10582,1514464130240,15 -10583,1514464243560,16 -10584,1514464325882,15 -10585,1514464393552,16 -10586,1514464455046,16 -10587,1514464512377,16 -10588,1514464566964,16 -10589,1514464619296,15 -10590,1514464667046,15 -10591,1514464688638,15 -10592,1514464710904,16 -10593,1514464723146,16 -10594,1514464737940,20 -10595,1514464759555,21 -10596,1514464801022,23 -10597,1514464835719,23 -10598,1514464964730,24 -10599,1514465120723,24 -10600,1514465216855,25 -10601,1514465304980,25 -10602,1514465396283,25 -10603,1514465480159,25 -10604,1514465518128,24 -10605,1514465651521,26 -10606,1514465920243,25 -10607,1514466089938,25 -10608,1514466181685,23 -10609,1514466346396,23 -10610,1514466443376,23 -10611,1514466465990,22 -10612,1514466617047,23 -10613,1514466769502,24 -10614,1514466913428,23 -10615,1514467062433,22 -10616,1514467092145,22 -10617,1514467181225,23 -10618,1514467312924,23 -10619,1514467457210,22 -10620,1514467609002,21 -10621,1514467741145,21 -10622,1514467830003,21 -10623,1514467865303,21 -10624,1514467952640,22 -10625,1514468035024,21 -10626,1514468057232,20 -10627,1514468171537,22 -10628,1514468272074,22 -10629,1514468296841,21 -10630,1514468331477,22 -10631,1514468389330,22 -10632,1514468420304,22 -10633,1514468504267,22 -10634,1514468558802,23 -10635,1514468586789,22 -10636,1514468645167,24 -10637,1514468691198,24 -10638,1514468719574,24 -10639,1514468803649,26 -10640,1514469010450,25 -10641,1514469215583,25 -10642,1514469319566,24 -10643,1514469387279,24 -10644,1514469423035,25 -10645,1514469480702,25 -10646,1514469558978,26 -10647,1514469603984,26 -10648,1514469642168,26 -10649,1514469725935,27 -10650,1514469796864,26 -10651,1514469824932,26 -10652,1514469849860,28 -10653,1514470137302,29 -10654,1514470401185,28 -10655,1514470422465,27 -10656,1514470516766,28 -10657,1514470660264,28 -10658,1514470839571,28 -10659,1514470941563,28 -10660,1514471040846,28 -10661,1514471102036,27 -10662,1514471160680,27 -10663,1514471298994,28 -10664,1514471500787,27 -10665,1514471665250,27 -10666,1514471723569,26 -10667,1514471784237,26 -10668,1514471865282,26 -10669,1514472151970,26 -10670,1514472422380,25 -10671,1514472447915,24 -10672,1514472508040,25 -10673,1514472568772,25 -10674,1514472676167,25 -10675,1514472773801,24 -10676,1514472796287,24 -10677,1514472837335,25 -10678,1514472907572,25 -10679,1514472971842,25 -10680,1514473016668,24 -10681,1514473041611,24 -10682,1514473057122,25 -10683,1514473095748,29 -10684,1514473189579,30 -10685,1514473307031,29 -10686,1514473375069,28 -10687,1514473413303,28 -10688,1514473441423,28 -10689,1514473492113,29 -10690,1514473554437,29 -10691,1514473615991,29 -10692,1514473776265,30 -10693,1514473925820,30 -10694,1514473991331,30 -10695,1514474063178,31 -10696,1514474104045,32 -10697,1514474164837,33 -10698,1514474222451,33 -10699,1514474265210,34 -10700,1514474284328,34 -10701,1514474338679,37 -10702,1514474399316,38 -10703,1514474418260,38 -10704,1514474427449,41 -10705,1514474540856,51 -10706,1514474634045,51 -10707,1514474726105,50 -10708,1514474857416,49 -10709,1514475068018,49 -10710,1514475451207,48 -10711,1514475746405,46 -10712,1514475943518,46 -10713,1514476101285,44 -10714,1514476184409,44 -10715,1514476290512,43 -10716,1514476368116,43 -10717,1514476466947,43 -10718,1514476560807,42 -10719,1514476710118,42 -10720,1514476845175,41 -10721,1514476896552,40 -10722,1514476963160,41 -10723,1514477076046,40 -10724,1514477271361,39 -10725,1514477442734,39 -10726,1514477513354,37 -10727,1514477611029,38 -10728,1514477734438,37 -10729,1514477900316,36 -10730,1514478140721,35 -10731,1514478278722,35 -10732,1514478327783,34 -10733,1514478365920,34 -10734,1514478411028,35 -10735,1514478475109,36 -10736,1514478555032,36 -10737,1514478716550,36 -10738,1514478845529,35 -10739,1514478972330,35 -10740,1514479084996,34 -10741,1514479200956,33 -10742,1514479365599,32 -10743,1514479508563,30 -10744,1514479550521,29 -10745,1514479575795,31 -10746,1514479745709,32 -10747,1514479834250,31 -10748,1514479956235,31 -10749,1514480046746,31 -10750,1514480085501,30 -10751,1514480175896,30 -10752,1514480362476,30 -10753,1514480583346,30 -10754,1514480727716,29 -10755,1514480881952,27 -10756,1514481000859,27 -10757,1514481129693,27 -10758,1514481260207,25 -10759,1514481315985,24 -10760,1514481357947,23 -10761,1514481385770,24 -10762,1514481439636,24 -10763,1514481553591,24 -10764,1514481751842,23 -10765,1514481894033,22 -10766,1514481945653,20 -10767,1514482004482,20 -10768,1514482032564,20 -10769,1514482064209,19 -10770,1514482144551,19 -10771,1514482211999,18 -10772,1514482247706,18 -10773,1514482279787,18 -10774,1514482301664,17 -10775,1514482395513,19 -10776,1514482503602,17 -10777,1514482592928,17 -10778,1514482740163,16 -10779,1514482864764,16 -10780,1514482917081,15 -10781,1514482942131,13 -10782,1514482982357,14 -10783,1514483016639,15 -10784,1514483174609,16 -10785,1514483341434,15 -10786,1514483401984,13 -10787,1514483456234,12 -10788,1514483477552,12 -10789,1514483499431,13 -10790,1514483508257,14 -10791,1514483547035,17 -10792,1514483601450,17 -10793,1514483643001,15 -10794,1514483753709,15 -10795,1514483862833,14 -10796,1514483913721,13 -10797,1514483962744,13 -10798,1514484004096,12 -10799,1514484042671,13 -10800,1514484057672,13 -10801,1514484098669,15 -10802,1514484199896,15 -10803,1514484290459,15 -10804,1514484318301,16 -10805,1514484346615,21 -10806,1514484384592,22 -10807,1514484443308,22 -10808,1514484483841,23 -10809,1514484517528,24 -10810,1514484687360,24 -10811,1514484885735,23 -10812,1514484972801,23 -10813,1514485041062,22 -10814,1514485159673,21 -10815,1514485273009,21 -10816,1514485324195,20 -10817,1514485401864,21 -10818,1514485494380,20 -10819,1514485548319,20 -10820,1514485563630,20 -10821,1514485575391,23 -10822,1514485802015,27 -10823,1514486036413,26 -10824,1514486156472,26 -10825,1514486279638,25 -10826,1514486350074,24 -10827,1514486404720,24 -10828,1514486498189,25 -10829,1514486786753,24 -10830,1514486994761,22 -10831,1514487030317,22 -10832,1514487094898,22 -10833,1514487205087,22 -10834,1514487298125,23 -10835,1514487326193,23 -10836,1514487415402,24 -10837,1514487541873,24 -10838,1514487742862,23 -10839,1514487900219,23 -10840,1514487941987,22 -10841,1514487971331,22 -10842,1514488108795,23 -10843,1514488290861,22 -10844,1514488388293,22 -10845,1514488498882,21 -10846,1514488645319,22 -10847,1514488758027,21 -10848,1514488864221,21 -10849,1514488941163,21 -10850,1514489035050,20 -10851,1514489125980,20 -10852,1514489147794,20 -10853,1514489166229,21 -10854,1514489205065,23 -10855,1514489249917,23 -10856,1514489265180,22 -10857,1514489362438,26 -10858,1514489473217,25 -10859,1514489577413,24 -10860,1514489661304,24 -10861,1514489713013,24 -10862,1514489806346,25 -10863,1514489894257,24 -10864,1514489950030,24 -10865,1514490070706,24 -10866,1514490224681,22 -10867,1514490299292,22 -10868,1514490337411,22 -10869,1514490402019,23 -10870,1514490530413,23 -10871,1514490624955,22 -10872,1514490669717,22 -10873,1514490701346,23 -10874,1514490730116,23 -10875,1514490780815,25 -10876,1514490894308,25 -10877,1514491017250,25 -10878,1514491121905,24 -10879,1514491184959,23 -10880,1514491256441,22 -10881,1514491323668,22 -10882,1514491371973,22 -10883,1514491440669,22 -10884,1514491475937,22 -10885,1514491521283,22 -10886,1514491632336,22 -10887,1514491753831,21 -10888,1514491785955,21 -10889,1514491810556,22 -10890,1514491862756,23 -10891,1514491924043,25 -10892,1514491979056,25 -10893,1514492022568,25 -10894,1514492180917,25 -10895,1514492413996,24 -10896,1514492544151,23 -10897,1514492625552,23 -10898,1514492706282,22 -10899,1514492872990,22 -10900,1514493048712,21 -10901,1514493150376,21 -10902,1514493204222,20 -10903,1514493253321,20 -10904,1514493310735,20 -10905,1514493339544,20 -10906,1514493347873,21 -10907,1514493377200,27 -10908,1514493422616,28 -10909,1514493480251,29 -10910,1514493552826,29 -10911,1514493587642,29 -10912,1514493664745,30 -10913,1514493713256,30 -10914,1514493741336,30 -10915,1514493816037,31 -10916,1514493970560,31 -10917,1514494084127,30 -10918,1514494163897,29 -10919,1514494232379,29 -10920,1514494281245,29 -10921,1514494338701,31 -10922,1514494371504,33 -10923,1514494389582,34 -10924,1514494467068,37 -10925,1514494545081,36 -10926,1514494586890,36 -10927,1514494630981,37 -10928,1514494920940,38 -10929,1514495323670,38 -10930,1514495739759,36 -10931,1514496049147,35 -10932,1514496150116,34 -10933,1514496255026,34 -10934,1514496394745,33 -10935,1514496671017,33 -10936,1514496867215,32 -10937,1514497136812,31 -10938,1514497380388,30 -10939,1514497467410,29 -10940,1514497535726,28 -10941,1514497629305,28 -10942,1514497714720,29 -10943,1514497793747,27 -10944,1514497893467,27 -10945,1514497964067,27 -10946,1514497982457,26 -10947,1514498072459,29 -10948,1514498173240,28 -10949,1514498228356,27 -10950,1514498322714,26 -10951,1514498583078,26 -10952,1514498788421,25 -10953,1514498911889,25 -10954,1514499035526,25 -10955,1514499088936,24 -10956,1514499292699,25 -10957,1514499463373,25 -10958,1514499606743,24 -10959,1514499758750,23 -10960,1514499797098,22 -10961,1514499829170,23 -10962,1514499854306,24 -10963,1514499885611,25 -10964,1514499963373,25 -10965,1514500055761,25 -10966,1514500095281,25 -10967,1514500140725,25 -10968,1514500204918,25 -10969,1514500278741,25 -10970,1514500333067,25 -10971,1514500364871,24 -10972,1514500442965,25 -10973,1514500562656,25 -10974,1514500648884,24 -10975,1514500766422,25 -10976,1514500884418,24 -10977,1514500915313,23 -10978,1514500954383,23 -10979,1514500989927,24 -10980,1514501022259,24 -10981,1514501047052,25 -10982,1514501174282,25 -10983,1514501295004,25 -10984,1514501327267,24 -10985,1514501387460,26 -10986,1514501547859,25 -10987,1514501650796,24 -10988,1514501662994,23 -10989,1514501688464,27 -10990,1514501723313,29 -10991,1514501751187,30 -10992,1514501766341,31 -10993,1514501923714,34 -10994,1514502059509,34 -10995,1514502110490,33 -10996,1514502157821,33 -10997,1514502179416,33 -10998,1514502292174,35 -10999,1514502399365,35 -11000,1514502454668,34 -11001,1514502493567,34 -11002,1514502557284,34 -11003,1514502647098,34 -11004,1514502684836,34 -11005,1514502847450,34 -11006,1514503035802,34 -11007,1514503285767,35 -11008,1514503564179,35 -11009,1514503732564,34 -11010,1514503864202,33 -11011,1514504044158,33 -11012,1514504235688,32 -11013,1514504341111,31 -11014,1514504388333,31 -11015,1514504432511,32 -11016,1514504570238,33 -11017,1514504776548,32 -11018,1514504938387,31 -11019,1514505032679,30 -11020,1514505068404,30 -11021,1514505105714,31 -11022,1514505141609,32 -11023,1514505200526,33 -11024,1514505252285,35 -11025,1514505287422,36 -11026,1514505312697,37 -11027,1514505354888,40 -11028,1514505573867,41 -11029,1514505787196,40 -11030,1514505897091,39 -11031,1514506040023,38 -11032,1514506156148,37 -11033,1514506341938,37 -11034,1514506487169,36 -11035,1514506605827,35 -11036,1514506902684,35 -11037,1514507149573,33 -11038,1514507231385,31 -11039,1514507341353,31 -11040,1514507476277,30 -11041,1514507592849,29 -11042,1514507685087,27 -11043,1514507719801,28 -11044,1514507865827,29 -11045,1514508016503,27 -11046,1514508032072,26 -11047,1514508047061,31 -11048,1514508078151,34 -11049,1514508103650,36 -11050,1514508463068,38 -11051,1514508905349,36 -11052,1514509058742,35 -11053,1514509224422,33 -11054,1514509376233,32 -11055,1514509420539,31 -11056,1514509520729,32 -11057,1514509624061,31 -11058,1514509733557,29 -11059,1514509817937,28 -11060,1514509840631,28 -11061,1514509875401,29 -11062,1514509920136,30 -11063,1514509992444,31 -11064,1514510158837,31 -11065,1514510406892,30 -11066,1514510606321,28 -11067,1514510726483,28 -11068,1514510821293,27 -11069,1514510859348,27 -11070,1514510871189,27 -11071,1514510919178,31 -11072,1514510977014,31 -11073,1514511007981,31 -11074,1514511029591,31 -11075,1514511144132,33 -11076,1514511256630,33 -11077,1514511288082,32 -11078,1514511322686,33 -11079,1514511525658,32 -11080,1514511826312,33 -11081,1514511993102,33 -11082,1514512084791,32 -11083,1514512179715,30 -11084,1514512251632,29 -11085,1514512299542,30 -11086,1514512405451,29 -11087,1514512547962,28 -11088,1514512675270,27 -11089,1514512756740,28 -11090,1514512794843,28 -11091,1514512818771,29 -11092,1514512868681,31 -11093,1514513030275,33 -11094,1514513253671,32 -11095,1514513411445,31 -11096,1514513505701,30 -11097,1514513567917,30 -11098,1514513642517,31 -11099,1514513696968,31 -11100,1514513708830,31 -11101,1514513774158,37 -11102,1514513811892,37 -11103,1514513833985,38 -11104,1514513881520,41 -11105,1514513933999,42 -11106,1514513982093,42 -11107,1514514092126,42 -11108,1514514226157,42 -11109,1514514331410,41 -11110,1514514408968,39 -11111,1514514467135,40 -11112,1514514535067,39 -11113,1514514693574,39 -11114,1514514876488,38 -11115,1514515002838,37 -11116,1514515073249,37 -11117,1514515104366,36 -11118,1514515263256,37 -11119,1514515426382,36 -11120,1514515517167,35 -11121,1514515612105,35 -11122,1514515659936,34 -11123,1514515692314,35 -11124,1514515736890,36 -11125,1514515879832,37 -11126,1514516037785,37 -11127,1514516216580,38 -11128,1514516422245,37 -11129,1514516549585,36 -11130,1514516743806,34 -11131,1514516903706,34 -11132,1514516965119,32 -11133,1514517049199,32 -11134,1514517278988,31 -11135,1514517538926,30 -11136,1514517623274,29 -11137,1514517652018,27 -11138,1514517838245,29 -11139,1514518026059,27 -11140,1514518140328,26 -11141,1514518354278,24 -11142,1514518485130,23 -11143,1514518574121,22 -11144,1514518682874,22 -11145,1514518765581,20 -11146,1514518827430,20 -11147,1514518954680,20 -11148,1514519089300,21 -11149,1514519127510,21 -11150,1514519162457,22 -11151,1514519270357,23 -11152,1514519365725,21 -11153,1514519398160,20 -11154,1514519426829,20 -11155,1514519447667,20 -11156,1514519466122,22 -11157,1514519482399,23 -11158,1514519553016,25 -11159,1514519639404,25 -11160,1514519674092,23 -11161,1514519715733,25 -11162,1514519797220,26 -11163,1514519883044,25 -11164,1514519940629,24 -11165,1514519988349,24 -11166,1514520030178,23 -11167,1514520074678,23 -11168,1514520117359,23 -11169,1514520143943,23 -11170,1514520234788,23 -11171,1514520343079,25 -11172,1514520411600,25 -11173,1514520458782,24 -11174,1514520486941,25 -11175,1514520538201,27 -11176,1514520581692,27 -11177,1514520644661,27 -11178,1514520780144,28 -11179,1514520914687,27 -11180,1514521100435,26 -11181,1514521295082,25 -11182,1514521384666,24 -11183,1514521421168,23 -11184,1514521439675,23 -11185,1514521549913,24 -11186,1514521721493,24 -11187,1514521803077,23 -11188,1514521847477,22 -11189,1514522003572,22 -11190,1514522218232,22 -11191,1514522322366,20 -11192,1514522350672,21 -11193,1514522393892,22 -11194,1514522435714,21 -11195,1514522490664,21 -11196,1514522539287,20 -11197,1514522617022,20 -11198,1514522691936,20 -11199,1514522703685,18 -11200,1514522741518,21 -11201,1514522779599,25 -11202,1514522805468,25 -11203,1514522836769,26 -11204,1514522892029,29 -11205,1514522929973,29 -11206,1514523078919,31 -11207,1514523267935,31 -11208,1514523395044,30 -11209,1514523511258,29 -11210,1514523657849,28 -11211,1514523792930,28 -11212,1514523824652,28 -11213,1514523843357,29 -11214,1514523869301,31 -11215,1514523895370,33 -11216,1514523933126,34 -11217,1514524296978,36 -11218,1514524718574,36 -11219,1514524891718,35 -11220,1514525038247,34 -11221,1514525206858,33 -11222,1514525387521,32 -11223,1514525570566,32 -11224,1514525698326,32 -11225,1514525752602,32 -11226,1514525845088,32 -11227,1514525921068,32 -11228,1514526039379,31 -11229,1514526154009,30 -11230,1514526295493,30 -11231,1514526458328,29 -11232,1514526526856,28 -11233,1514526691450,28 -11234,1514526880384,27 -11235,1514526960828,25 -11236,1514526994087,25 -11237,1514527013609,26 -11238,1514527112561,29 -11239,1514527140892,28 -11240,1514527179823,29 -11241,1514527219862,30 -11242,1514527298950,29 -11243,1514527386169,29 -11244,1514527477180,28 -11245,1514527598335,28 -11246,1514527792925,27 -11247,1514528055561,25 -11248,1514528225898,25 -11249,1514528308345,23 -11250,1514528354812,23 -11251,1514528370315,23 -11252,1514528589508,25 -11253,1514528778527,23 -11254,1514528847473,23 -11255,1514528948096,23 -11256,1514528993606,23 -11257,1514529029993,24 -11258,1514529110891,26 -11259,1514529175682,25 -11260,1514529210382,24 -11261,1514529267780,25 -11262,1514529526213,26 -11263,1514529763150,25 -11264,1514529868878,24 -11265,1514529997698,23 -11266,1514530053952,22 -11267,1514530104861,23 -11268,1514530156066,22 -11269,1514530181088,23 -11270,1514530259952,24 -11271,1514530370578,24 -11272,1514530435008,24 -11273,1514530502885,23 -11274,1514530587459,23 -11275,1514530767891,23 -11276,1514530937463,22 -11277,1514530989154,22 -11278,1514531024078,21 -11279,1514531076769,21 -11280,1514531138851,21 -11281,1514531338907,21 -11282,1514531536561,19 -11283,1514531591561,19 -11284,1514531640559,19 -11285,1514531652793,19 -11286,1514531729789,22 -11287,1514531869516,22 -11288,1514531955049,21 -11289,1514531981219,21 -11290,1514532000920,21 -11291,1514532036082,22 -11292,1514532070694,22 -11293,1514532100374,23 -11294,1514532122120,24 -11295,1514532148702,26 -11296,1514532177106,26 -11297,1514532238618,27 -11298,1514532293263,27 -11299,1514532370018,27 -11300,1514532402987,28 -11301,1514532481218,29 -11302,1514532551467,29 -11303,1514532594446,29 -11304,1514532705889,31 -11305,1514532801562,30 -11306,1514532843058,30 -11307,1514532881585,31 -11308,1514532901320,31 -11309,1514532947754,33 -11310,1514533028692,34 -11311,1514533093816,34 -11312,1514533119518,33 -11313,1514533287343,36 -11314,1514533432742,36 -11315,1514533535605,36 -11316,1514533612710,37 -11317,1514533742347,38 -11318,1514533915855,37 -11319,1514534067672,36 -11320,1514534119865,35 -11321,1514534144521,36 -11322,1514534338926,37 -11323,1514534589623,37 -11324,1514534734770,35 -11325,1514534868616,35 -11326,1514534955346,34 -11327,1514535007175,33 -11328,1514535206075,34 -11329,1514535375443,33 -11330,1514535501077,32 -11331,1514535603685,31 -11332,1514535749371,31 -11333,1514535882096,29 -11334,1514535921613,29 -11335,1514535975570,29 -11336,1514536025691,29 -11337,1514536057562,29 -11338,1514536111566,32 -11339,1514536177874,32 -11340,1514536204103,33 -11341,1514536255723,35 -11342,1514536329634,35 -11343,1514536453475,35 -11344,1514536583578,35 -11345,1514536670051,34 -11346,1514536728685,33 -11347,1514536750216,33 -11348,1514536785494,36 -11349,1514536925281,36 -11350,1514537075675,35 -11351,1514537256279,34 -11352,1514537415149,35 -11353,1514537452943,34 -11354,1514537556733,34 -11355,1514537679727,34 -11356,1514537790385,33 -11357,1514537884477,32 -11358,1514538062852,32 -11359,1514538270466,31 -11360,1514538366075,30 -11361,1514538435102,30 -11362,1514538492521,30 -11363,1514538568980,29 -11364,1514538676924,28 -11365,1514538738455,28 -11366,1514538783409,28 -11367,1514538910185,27 -11368,1514539013917,27 -11369,1514539059234,26 -11370,1514539349853,26 -11371,1514539674924,26 -11372,1514539784970,24 -11373,1514539874613,24 -11374,1514539971303,23 -11375,1514540062264,23 -11376,1514540257863,21 -11377,1514540443454,20 -11378,1514540471687,19 -11379,1514540637101,20 -11380,1514540708637,19 -11381,1514540736961,18 -11382,1514540748631,17 -11383,1514540786711,20 -11384,1514540837749,20 -11385,1514540866371,19 -11386,1514540878330,21 -11387,1514541020113,23 -11388,1514541119378,22 -11389,1514541172870,22 -11390,1514541267010,22 -11391,1514541443786,22 -11392,1514541733409,20 -11393,1514541927087,20 -11394,1514541959619,20 -11395,1514542046758,20 -11396,1514542129085,21 -11397,1514542147717,21 -11398,1514542187545,23 -11399,1514542215480,22 -11400,1514542346723,23 -11401,1514542487073,23 -11402,1514542532092,22 -11403,1514542573498,22 -11404,1514542651462,23 -11405,1514542757054,22 -11406,1514542848511,21 -11407,1514542893125,21 -11408,1514542924433,22 -11409,1514542943196,23 -11410,1514542977866,25 -11411,1514543035202,26 -11412,1514543113406,27 -11413,1514543167611,27 -11414,1514543228887,27 -11415,1514543318701,27 -11416,1514543373806,26 -11417,1514543504084,26 -11418,1514543625362,25 -11419,1514543679248,25 -11420,1514543730578,25 -11421,1514543740142,25 -11422,1514543838211,32 -11423,1514543960617,31 -11424,1514544005200,30 -11425,1514544090669,30 -11426,1514544203537,30 -11427,1514544303757,29 -11428,1514544396385,29 -11429,1514544458163,29 -11430,1514544503405,28 -11431,1514544556075,28 -11432,1514544599909,28 -11433,1514544736980,29 -11434,1514544827718,27 -11435,1514544859420,28 -11436,1514544891183,28 -11437,1514545088157,29 -11438,1514545371509,29 -11439,1514545672799,29 -11440,1514545751562,27 -11441,1514545839172,28 -11442,1514546082774,28 -11443,1514546316333,27 -11444,1514546383368,26 -11445,1514546448874,26 -11446,1514546484341,27 -11447,1514546555821,27 -11448,1514546624510,28 -11449,1514546636416,29 -11450,1514546665424,33 -11451,1514546728469,35 -11452,1514546832269,35 -11453,1514546912690,34 -11454,1514546966729,35 -11455,1514547034189,35 -11456,1514547102261,35 -11457,1514547292450,35 -11458,1514547451983,34 -11459,1514547613799,33 -11460,1514547799212,32 -11461,1514547969477,31 -11462,1514548193174,31 -11463,1514548293007,30 -11464,1514548483295,29 -11465,1514548691627,29 -11466,1514548730334,28 -11467,1514548869931,28 -11468,1514548979617,28 -11469,1514549079591,27 -11470,1514549219215,27 -11471,1514549300512,26 -11472,1514549370475,25 -11473,1514549432786,25 -11474,1514549525204,24 -11475,1514549641924,24 -11476,1514549719645,22 -11477,1514549745005,22 -11478,1514549796339,22 -11479,1514549856989,23 -11480,1514549879679,21 -11481,1514550002755,23 -11482,1514550103259,22 -11483,1514550252175,23 -11484,1514550425162,22 -11485,1514550486708,21 -11486,1514550561637,21 -11487,1514550638224,23 -11488,1514550761210,22 -11489,1514550884013,21 -11490,1514550995851,20 -11491,1514551116866,19 -11492,1514551151276,18 -11493,1514551186573,18 -11494,1514551241728,18 -11495,1514551279869,18 -11496,1514551305291,18 -11497,1514551336891,18 -11498,1514551359441,19 -11499,1514551460418,20 -11500,1514551504734,20 -11501,1514551539708,21 -11502,1514551555256,20 -11503,1514551606066,22 -11504,1514551644719,23 -11505,1514551731986,23 -11506,1514551835933,22 -11507,1514551891142,21 -11508,1514551998411,21 -11509,1514552098404,21 -11510,1514552179848,21 -11511,1514552245523,21 -11512,1514552260557,20 -11513,1514552269386,23 -11514,1514552284811,28 -11515,1514552312317,31 -11516,1514552371446,33 -11517,1514552422561,33 -11518,1514552449433,33 -11519,1514552497251,35 -11520,1514552603595,35 -11521,1514552726588,35 -11522,1514552791624,36 -11523,1514552853414,36 -11524,1514552927480,36 -11525,1514552951998,37 -11526,1514553083097,39 -11527,1514553302407,39 -11528,1514553568665,37 -11529,1514553760495,36 -11530,1514553848917,36 -11531,1514553902588,35 -11532,1514553978245,36 -11533,1514554039526,37 -11534,1514554081352,36 -11535,1514554109866,37 -11536,1514554118736,39 -11537,1514554262022,49 -11538,1514554374785,49 -11539,1514554514633,47 -11540,1514554611742,47 -11541,1514554663072,46 -11542,1514554698514,47 -11543,1514555017581,48 -11544,1514555489827,47 -11545,1514555838602,45 -11546,1514556027380,44 -11547,1514556057654,44 -11548,1514556224122,45 -11549,1514556390389,45 -11550,1514556501229,47 -11551,1514556679189,47 -11552,1514556778665,46 -11553,1514556845992,46 -11554,1514556971821,46 -11555,1514557176705,46 -11556,1514557336753,45 -11557,1514557472449,45 -11558,1514557621280,44 -11559,1514557774885,42 -11560,1514557988761,42 -11561,1514558088013,40 -11562,1514558245386,40 -11563,1514558433578,38 -11564,1514558483178,38 -11565,1514558743390,38 -11566,1514559074479,36 -11567,1514559181889,35 -11568,1514559256758,35 -11569,1514559353939,34 -11570,1514559407592,34 -11571,1514559441944,34 -11572,1514559510448,34 -11573,1514559552007,34 -11574,1514559740379,35 -11575,1514559869622,33 -11576,1514560001618,31 -11577,1514560163050,31 -11578,1514560220720,31 -11579,1514560260396,31 -11580,1514560319328,31 -11581,1514560357712,32 -11582,1514560372683,31 -11583,1514560482710,35 -11584,1514560666466,33 -11585,1514560837082,32 -11586,1514560912550,32 -11587,1514560988758,31 -11588,1514561070850,29 -11589,1514561203992,28 -11590,1514561316183,27 -11591,1514561351939,26 -11592,1514561425218,26 -11593,1514561502540,25 -11594,1514561583720,24 -11595,1514561704262,24 -11596,1514561812040,22 -11597,1514561868738,22 -11598,1514561883853,21 -11599,1514561962170,24 -11600,1514562078064,23 -11601,1514562153738,22 -11602,1514562203510,21 -11603,1514562245076,22 -11604,1514562390520,22 -11605,1514562518239,21 -11606,1514562529956,20 -11607,1514562548615,22 -11608,1514562588071,23 -11609,1514562623288,22 -11610,1514562644736,22 -11611,1514562710953,23 -11612,1514562774982,22 -11613,1514562814228,23 -11614,1514562852725,25 -11615,1514562907557,26 -11616,1514563065886,27 -11617,1514563260315,27 -11618,1514563344986,26 -11619,1514563369955,26 -11620,1514563562788,28 -11621,1514563771513,26 -11622,1514563841184,25 -11623,1514563934705,24 -11624,1514564015072,24 -11625,1514564069619,24 -11626,1514564107621,25 -11627,1514564230197,24 -11628,1514564351371,24 -11629,1514564396643,22 -11630,1514564453842,22 -11631,1514564491814,21 -11632,1514564640673,22 -11633,1514564802318,21 -11634,1514564889699,20 -11635,1514564947894,19 -11636,1514565097139,20 -11637,1514565128945,24 -11638,1514565210035,25 -11639,1514565328858,25 -11640,1514565403471,24 -11641,1514565498261,23 -11642,1514565585746,24 -11643,1514565610951,25 -11644,1514565712550,25 -11645,1514565850570,24 -11646,1514565953111,23 -11647,1514566084452,23 -11648,1514566237720,23 -11649,1514566420238,22 -11650,1514566530275,21 -11651,1514566626201,21 -11652,1514566697190,21 -11653,1514566743315,20 -11654,1514566992990,21 -11655,1514567242260,20 -11656,1514567294527,18 -11657,1514567322921,19 -11658,1514567356989,19 -11659,1514567410448,19 -11660,1514567445411,19 -11661,1514567493657,19 -11662,1514567562446,19 -11663,1514567694223,18 -11664,1514567820116,18 -11665,1514567855142,17 -11666,1514567925378,17 -11667,1514567986477,17 -11668,1514568017840,15 -11669,1514568096360,16 -11670,1514568195506,15 -11671,1514568289278,15 -11672,1514568340405,15 -11673,1514568355170,15 -11674,1514568364316,17 -11675,1514568544669,20 -11676,1514568692889,19 -11677,1514568817325,18 -11678,1514568888196,17 -11679,1514568937617,17 -11680,1514568975616,17 -11681,1514569035534,18 -11682,1514569106282,18 -11683,1514569147354,19 -11684,1514569185626,20 -11685,1514569253728,20 -11686,1514569295632,19 -11687,1514569435445,20 -11688,1514569641756,18 -11689,1514569858275,18 -11690,1514569880992,17 -11691,1514569925508,18 -11692,1514569984160,18 -11693,1514570057478,18 -11694,1514570122054,17 -11695,1514570140641,17 -11696,1514570152736,18 -11697,1514570210400,20 -11698,1514570394835,21 -11699,1514570603977,21 -11700,1514570690966,20 -11701,1514570761853,19 -11702,1514570803235,19 -11703,1514570821812,19 -11704,1514570854009,21 -11705,1514570892930,21 -11706,1514570951770,22 -11707,1514570992549,22 -11708,1514571050550,24 -11709,1514571129067,25 -11710,1514571169369,24 -11711,1514571245490,26 -11712,1514571413470,26 -11713,1514571528557,25 -11714,1514571572407,25 -11715,1514571604011,26 -11716,1514571745555,27 -11717,1514571818055,27 -11718,1514571865445,26 -11719,1514571906812,27 -11720,1514571981632,28 -11721,1514572055607,28 -11722,1514572207021,28 -11723,1514572361393,27 -11724,1514572405688,26 -11725,1514572489155,27 -11726,1514572579657,27 -11727,1514572634348,27 -11728,1514572665588,27 -11729,1514572716364,28 -11730,1514572805203,29 -11731,1514572879710,28 -11732,1514572924447,29 -11733,1514573028062,29 -11734,1514573131032,28 -11735,1514573191734,28 -11736,1514573322773,27 -11737,1514573494553,27 -11738,1514573595083,27 -11739,1514573714243,27 -11740,1514573820332,25 -11741,1514573871379,26 -11742,1514573919915,26 -11743,1514573962259,26 -11744,1514574021786,27 -11745,1514574086018,28 -11746,1514574237180,27 -11747,1514574422023,26 -11748,1514574498735,26 -11749,1514574556897,25 -11750,1514574621385,25 -11751,1514574656014,25 -11752,1514574671957,25 -11753,1514574687067,28 -11754,1514574698890,31 -11755,1514574717138,37 -11756,1514575143902,39 -11757,1514575521683,39 -11758,1514575637811,38 -11759,1514575702416,38 -11760,1514575826490,37 -11761,1514575943890,37 -11762,1514575985804,37 -11763,1514576070551,37 -11764,1514576169506,38 -11765,1514576302946,36 -11766,1514576435970,36 -11767,1514576519257,35 -11768,1514576580517,35 -11769,1514576715445,35 -11770,1514576878147,35 -11771,1514576982165,34 -11772,1514577048605,33 -11773,1514577087288,33 -11774,1514577136855,34 -11775,1514577174727,36 -11776,1514577186530,37 -11777,1514577381602,43 -11778,1514577627080,42 -11779,1514577887229,40 -11780,1514578119812,39 -11781,1514578290327,39 -11782,1514578434796,38 -11783,1514578571721,37 -11784,1514578668975,36 -11785,1514578857342,37 -11786,1514579056135,35 -11787,1514579157532,34 -11788,1514579237648,34 -11789,1514579290880,33 -11790,1514579342569,33 -11791,1514579402689,34 -11792,1514579574443,33 -11793,1514579810032,32 -11794,1514579962593,31 -11795,1514580127990,31 -11796,1514580264015,29 -11797,1514580394298,31 -11798,1514580500010,29 -11799,1514580589632,29 -11800,1514580670782,28 -11801,1514580899648,27 -11802,1514581095174,26 -11803,1514581162819,25 -11804,1514581286592,26 -11805,1514581400380,26 -11806,1514581545059,25 -11807,1514581714236,24 -11808,1514581836415,23 -11809,1514581972287,22 -11810,1514582051368,21 -11811,1514582129409,21 -11812,1514582186209,21 -11813,1514582201235,20 -11814,1514582248675,22 -11815,1514582349864,22 -11816,1514582440541,22 -11817,1514582511875,21 -11818,1514582607815,21 -11819,1514582664991,21 -11820,1514582702589,21 -11821,1514582744071,21 -11822,1514582765972,21 -11823,1514582790230,22 -11824,1514582824304,22 -11825,1514582859156,23 -11826,1514582882019,23 -11827,1514582916864,24 -11828,1514582996189,25 -11829,1514583064247,25 -11830,1514583136802,24 -11831,1514583212709,24 -11832,1514583328406,23 -11833,1514583450375,23 -11834,1514583492079,22 -11835,1514583539570,22 -11836,1514583617113,21 -11837,1514583664430,21 -11838,1514583735786,20 -11839,1514583825438,20 -11840,1514583873610,18 -11841,1514583917801,18 -11842,1514583964913,19 -11843,1514584006197,18 -11844,1514584057029,18 -11845,1514584089878,18 -11846,1514584174487,18 -11847,1514584314122,17 -11848,1514584485105,16 -11849,1514584541947,15 -11850,1514584562014,14 -11851,1514584577625,14 -11852,1514584605779,16 -11853,1514584646643,18 -11854,1514584675467,19 -11855,1514584697104,23 -11856,1514584729245,26 -11857,1514584848404,27 -11858,1514585028941,26 -11859,1514585165022,25 -11860,1514585225040,24 -11861,1514585253514,24 -11862,1514585395870,25 -11863,1514585558304,25 -11864,1514585596270,24 -11865,1514585786553,23 -11866,1514585930322,24 -11867,1514586022843,23 -11868,1514586123298,23 -11869,1514586207591,23 -11870,1514586330795,22 -11871,1514586446754,21 -11872,1514586498842,20 -11873,1514586531340,20 -11874,1514586545104,22 -11875,1514586608792,25 -11876,1514586659175,26 -11877,1514586821447,29 -11878,1514586983057,29 -11879,1514587079398,27 -11880,1514587136093,27 -11881,1514587200315,27 -11882,1514587229733,27 -11883,1514587342204,28 -11884,1514587523246,27 -11885,1514587677056,27 -11886,1514587874015,26 -11887,1514588048461,25 -11888,1514588267962,24 -11889,1514588456718,24 -11890,1514588667162,24 -11891,1514588877197,23 -11892,1514589013648,22 -11893,1514589084242,22 -11894,1514589158766,21 -11895,1514589207902,21 -11896,1514589294911,21 -11897,1514589348507,20 -11898,1514589409551,20 -11899,1514589483598,20 -11900,1514589541405,20 -11901,1514589617870,20 -11902,1514589668871,18 -11903,1514589692851,18 -11904,1514589759758,19 -11905,1514589840085,19 -11906,1514589904367,18 -11907,1514590371066,18 -11908,1514591181715,17 -11909,1514591816709,16 -11910,1514592455927,14 -11911,1514592799800,13 -11912,1514593244352,12 -11913,1514594050203,12 -11914,1514594974213,11 -11915,1514595636110,12 -11916,1514595664272,11 -11917,1514595695658,10 -11918,1514595711773,10 -11919,1514595738552,10 -11920,1514595773533,10 -11921,1514595812425,11 -11922,1514595850315,11 -11923,1514595907854,11 -11924,1514595950717,12 -11925,1514596046956,11 -11926,1514596163275,12 -11927,1514596204286,11 -11928,1514596249034,12 -11929,1514596267344,12 -11930,1514596271469,12 -11931,1514596305763,19 -11932,1514596338958,19 -11933,1514596356662,19 -11934,1514596375981,21 -11935,1514596401625,23 -11936,1514596423465,24 -11937,1514596498581,27 -11938,1514596614723,26 -11939,1514596734005,26 -11940,1514596784453,25 -11941,1514597048393,25 -11942,1514597500459,25 -11943,1514597759847,24 -11944,1514597810278,23 -11945,1514597854963,23 -11946,1514597895978,24 -11947,1514598022826,24 -11948,1514598165293,24 -11949,1514598196152,23 -11950,1514598252053,23 -11951,1514598322189,23 -11952,1514598393519,25 -11953,1514598442709,24 -11954,1514598497327,25 -11955,1514598597886,26 -11956,1514598732510,26 -11957,1514598804777,27 -11958,1514598833707,26 -11959,1514598939992,27 -11960,1514598950614,26 -11961,1514598987344,32 -11962,1514599014466,33 -11963,1514599062077,35 -11964,1514599130046,35 -11965,1514599180988,36 -11966,1514599231539,36 -11967,1514599334896,37 -11968,1514599466719,36 -11969,1514599609352,36 -11970,1514599623406,35 -11971,1514599787613,40 -11972,1514600006455,39 -11973,1514600190193,38 -11974,1514600353664,38 -11975,1514600361324,39 -11976,1514600376804,50 -11977,1514600402492,57 -11978,1514600457905,60 -11979,1514600581387,61 -11980,1514600749108,61 -11981,1514600957477,61 -11982,1514601080843,61 -11983,1514601122760,61 -11984,1514601267686,62 -11985,1514601438635,62 -11986,1514601635252,61 -11987,1514601835678,60 -11988,1514601857258,59 -11989,1514601927536,63 -11990,1514601932098,63 -11991,1514602056098,95 -11992,1514602257418,94 -11993,1514602467090,93 -11994,1514602597084,92 -11995,1514602731000,91 -11996,1514602772789,91 -11997,1514603039767,94 -11998,1514603331556,92 -11999,1514603559429,90 -12000,1514603827932,89 -12001,1514603925384,87 -12002,1514604054610,87 -12003,1514604311616,87 -12004,1514604508318,85 -12005,1514604602685,84 -12006,1514604800655,84 -12007,1514605045394,83 -12008,1514605798154,81 -12009,1514606510631,78 -12010,1514606827730,75 -12011,1514607251233,73 -12012,1514607572847,71 -12013,1514607808272,69 -12014,1514608114199,66 -12015,1514608477135,65 -12016,1514608898198,62 -12017,1514609343646,60 -12018,1514609398427,58 -12019,1514609454897,58 -12020,1514609607471,58 -12021,1514609772500,57 -12022,1514609856818,55 -12023,1514610091355,54 -12024,1514610315688,52 -12025,1514610364838,50 -12026,1514610626345,50 -12027,1514610897718,47 -12028,1514610973621,46 -12029,1514611080137,44 -12030,1514611107300,43 -12031,1514611155544,48 -12032,1514611242399,48 -12033,1514611265878,46 -12034,1514611306535,50 -12035,1514611414164,52 -12036,1514611504235,51 -12037,1514611816812,50 -12038,1514611824450,49 -12039,1514611866229,62 -12040,1514611937200,63 -12041,1514612023688,61 -12042,1514612202384,60 -12043,1514612358677,58 -12044,1514612391680,56 -12045,1514612697917,58 -12046,1514612974339,56 -12047,1514613081563,53 -12048,1514613180820,51 -12049,1514613311787,49 -12050,1514613387142,48 -12051,1514613499508,47 -12052,1514613572463,46 -12053,1514613772258,44 -12054,1514613988562,41 -12055,1514614087282,40 -12056,1514614159874,38 -12057,1514614247252,36 -12058,1514614330897,34 -12059,1514614423877,33 -12060,1514614518636,31 -12061,1514614641334,31 -12062,1514614715474,30 -12063,1514614805943,29 -12064,1514614873876,28 -12065,1514615026559,27 -12066,1514615201630,24 -12067,1514615243861,22 -12068,1514615330079,21 -12069,1514615420449,19 -12070,1514615461734,17 -12071,1514615493421,18 -12072,1514615519297,17 -12073,1514615576774,16 -12074,1514615621459,14 -12075,1514615676843,11 -12076,1514615720335,15 -12077,1514615779577,17 -12078,1514615858929,18 -12079,1514615869696,17 -12080,1514615888392,19 -12081,1514615900903,19 -12082,1514616030989,20 -12083,1514616129018,19 -12084,1514616182623,18 -12085,1514616302507,17 -12086,1514616422536,15 -12087,1514616482910,13 -12088,1514616496904,11 -12089,1514616504990,14 -12090,1514616514167,17 -12091,1514616528484,35 -12092,1514616577522,40 -12093,1514616720570,40 -12094,1514616837088,39 -12095,1514616891562,39 -12096,1514617014223,39 -12097,1514617041536,40 -12098,1514617114092,41 -12099,1514617197512,42 -12100,1514617216412,41 -12101,1514617241233,44 -12102,1514617287589,48 -12103,1514617415075,48 -12104,1514617577701,48 -12105,1514617922790,46 -12106,1514618490492,46 -12107,1514618764247,43 -12108,1514618902500,42 -12109,1514619162392,41 -12110,1514619352511,39 -12111,1514619383704,38 -12112,1514619407492,39 -12113,1514619517007,40 -12114,1514619528254,39 -12115,1514619535891,45 -12116,1514619579644,58 -12117,1514619630928,58 -12118,1514619656283,58 -12119,1514619678057,62 -12120,1514619931067,67 -12121,1514620034766,65 -12122,1514620430145,64 -12123,1514620493596,62 -12124,1514620805512,63 -12125,1514621546730,60 -12126,1514622135343,59 -12127,1514622300708,56 -12128,1514622387922,54 -12129,1514622483107,54 -12130,1514622526199,53 -12131,1514622620097,55 -12132,1514622732980,54 -12133,1514622800680,53 -12134,1514622808268,55 -12135,1514622843994,71 -12136,1514622901277,73 -12137,1514623004564,74 -12138,1514623087225,73 -12139,1514623412745,80 -12140,1514623442893,80 -12141,1514623526613,84 -12142,1514623576665,84 -12143,1514623629335,86 -12144,1514623750722,87 -12145,1514623942915,88 -12146,1514624089055,86 -12147,1514624699385,85 -12148,1514625583750,83 -12149,1514625787242,81 -12150,1514626025726,79 -12151,1514626355636,77 -12152,1514626712712,75 -12153,1514626920118,74 -12154,1514627177557,72 -12155,1514627257856,70 -12156,1514627368992,70 -12157,1514627643104,68 -12158,1514627971226,67 -12159,1514628209075,64 -12160,1514628898962,63 -12161,1514629435720,60 -12162,1514629500910,57 -12163,1514629596974,58 -12164,1514629730208,56 -12165,1514629777299,55 -12166,1514629881613,55 -12167,1514630107040,54 -12168,1514630376154,52 -12169,1514630568487,49 -12170,1514630718436,47 -12171,1514630723001,45 -12172,1514631013906,66 -12173,1514631296242,64 -12174,1514631643755,62 -12175,1514631797771,60 -12176,1514632328684,57 -12177,1514632368542,55 -12178,1514632429614,55 -12179,1514632447229,54 -12180,1514632572746,60 -12181,1514632606433,59 -12182,1514632654601,61 -12183,1514632681815,61 -12184,1514632824327,63 -12185,1514632889437,61 -12186,1514632913106,60 -12187,1514633063267,62 -12188,1514633142176,60 -12189,1514633340529,59 -12190,1514633370931,58 -12191,1514633571358,61 -12192,1514633831175,62 -12193,1514633859015,60 -12194,1514633908129,61 -12195,1514633919087,61 -12196,1514633931306,71 -12197,1514634321885,82 -12198,1514634511503,81 -12199,1514634747653,79 -12200,1514635006388,76 -12201,1514635096898,75 -12202,1514635229373,76 -12203,1514635344897,74 -12204,1514635683451,72 -12205,1514636109334,69 -12206,1514636392682,66 -12207,1514636540430,62 -12208,1514636686988,60 -12209,1514636972463,58 -12210,1514637147328,54 -12211,1514637454548,51 -12212,1514637708302,50 -12213,1514637804761,48 -12214,1514638015889,45 -12215,1514638372203,47 -12216,1514638491243,50 -12217,1514638538758,50 -12218,1514638650664,50 -12219,1514638726095,51 -12220,1514638758747,53 -12221,1514638833204,54 -12222,1514638911783,52 -12223,1514638986529,51 -12224,1514639059491,50 -12225,1514639135439,49 -12226,1514639139965,48 -12227,1514639375985,70 -12228,1514639574224,67 -12229,1514639761261,64 -12230,1514639801952,63 -12231,1514639816153,64 -12232,1514640164763,72 -12233,1514640542134,69 -12234,1514640732591,66 -12235,1514640996665,72 -12236,1514641274229,71 -12237,1514641418024,71 -12238,1514641737914,69 -12239,1514641823820,67 -12240,1514641950011,65 -12241,1514642137259,67 -12242,1514642141593,65 -12243,1514642309471,99 -12244,1514642548146,100 -12245,1514642610374,98 -12246,1514643002689,97 -12247,1514643480981,95 -12248,1514644230304,92 -12249,1514644538788,89 -12250,1514644762113,86 -12251,1514644814070,83 -12252,1514645014255,84 -12253,1514645085136,80 -12254,1514645221093,80 -12255,1514645261991,78 -12256,1514645380670,79 -12257,1514645484173,78 -12258,1514645592516,76 -12259,1514645864933,74 -12260,1514646278584,71 -12261,1514646589200,67 -12262,1514646816661,63 -12263,1514646824368,61 -12264,1514647030886,77 -12265,1514647367989,74 -12266,1514647607616,71 -12267,1514647704261,69 -12268,1514647741314,67 -12269,1514648055057,67 -12270,1514648075687,63 -12271,1514648103539,67 -12272,1514648140256,80 -12273,1514648710756,81 -12274,1514648960765,78 -12275,1514649208512,75 -12276,1514649212874,72 -12277,1514649615515,108 -12278,1514649770921,105 -12279,1514649872982,103 -12280,1514650270690,104 -12281,1514650777931,101 -12282,1514650920276,99 -12283,1514651169880,97 -12284,1514651538228,96 -12285,1514651585262,93 -12286,1514652175205,95 -12287,1514652950935,94 -12288,1514652972408,90 -12289,1514653207419,96 -12290,1514653591972,93 -12291,1514653655136,91 -12292,1514653891563,91 -12293,1514654209369,86 -12294,1514654526023,85 -12295,1514654713314,83 -12296,1514654832563,87 -12297,1514654951047,91 -12298,1514655024886,90 -12299,1514655126062,89 -12300,1514655491638,87 -12301,1514655508665,83 -12302,1514655709453,92 -12303,1514656086529,90 -12304,1514656657184,87 -12305,1514657187831,83 -12306,1514657418233,79 -12307,1514657669233,76 -12308,1514657735518,73 -12309,1514657958797,72 -12310,1514658211558,69 -12311,1514658253255,66 -12312,1514658686612,65 -12313,1514659114830,61 -12314,1514659132669,58 -12315,1514659167471,61 -12316,1514659484798,61 -12317,1514659845319,58 -12318,1514660012784,55 -12319,1514660177601,51 -12320,1514660194595,49 -12321,1514660224785,53 -12322,1514660305122,53 -12323,1514660398959,52 -12324,1514660797557,49 -12325,1514661297875,46 -12326,1514661414530,42 -12327,1514661614984,52 -12328,1514661871591,48 -12329,1514661948078,45 -12330,1514662048494,43 -12331,1514662056072,42 -12332,1514662132894,56 -12333,1514662214549,54 -12334,1514662269169,52 -12335,1514662384192,50 -12336,1514662774990,48 -12337,1514662844594,44 -12338,1514663040034,42 -12339,1514663060863,38 -12340,1514663122567,39 -12341,1514663176120,37 -12342,1514663203315,35 -12343,1514663271516,52 -12344,1514663352275,51 -12345,1514663443273,49 -12346,1514663529686,49 -12347,1514663603831,46 -12348,1514663791186,45 -12349,1514663857935,41 -12350,1514663953820,40 -12351,1514664101798,38 -12352,1514664165289,36 -12353,1514664292383,34 -12354,1514664370096,33 -12355,1514664523830,31 -12356,1514664646605,30 -12357,1514664736649,28 -12358,1514664882572,26 -12359,1514664926835,23 -12360,1514664931118,21 -12361,1514664959705,29 -12362,1514665146027,28 -12363,1514665183293,25 -12364,1514665231527,33 -12365,1514665372565,31 -12366,1514665470403,28 -12367,1514665587439,26 -12368,1514665674242,24 -12369,1514665774956,23 -12370,1514665878688,20 -12371,1514665975576,21 -12372,1514666016907,21 -12373,1514666028694,22 -12374,1514666082112,23 -12375,1514666128919,21 -12376,1514666182876,19 -12377,1514666227804,37 -12378,1514666320148,37 -12379,1514666334288,36 -12380,1514666446806,40 -12381,1514666553342,39 -12382,1514666781365,37 -12383,1514666936970,36 -12384,1514667071842,34 -12385,1514667290199,32 -12386,1514667340052,32 -12387,1514667351513,31 -12388,1514667380779,35 -12389,1514667392379,41 -12390,1514667463105,45 -12391,1514667527419,46 -12392,1514667575241,46 -12393,1514667732125,46 -12394,1514667792585,45 -12395,1514667974799,44 -12396,1514668041721,41 -12397,1514668125546,41 -12398,1514668163372,40 -12399,1514668180969,42 -12400,1514668324851,46 -12401,1514668470909,44 -12402,1514668494528,48 -12403,1514668525354,50 -12404,1514668645335,52 -12405,1514668858262,50 -12406,1514669099879,48 -12407,1514669169444,46 -12408,1514669263321,45 -12409,1514669306659,45 -12410,1514669452163,45 -12411,1514669466661,43 -12412,1514669703798,50 -12413,1514670197710,47 -12414,1514670587306,45 -12415,1514670955014,46 -12416,1514671323062,46 -12417,1514671449999,44 -12418,1514671631768,42 -12419,1514671859179,40 -12420,1514672045810,38 -12421,1514672073568,40 -12422,1514672171483,43 -12423,1514672176240,42 -12424,1514672442168,61 -12425,1514672754980,59 -12426,1514673057739,57 -12427,1514673362410,54 -12428,1514673453785,52 -12429,1514673521354,51 -12430,1514673927805,51 -12431,1514674461090,49 -12432,1514674583631,52 -12433,1514674604966,52 -12434,1514674654938,56 -12435,1514674793215,57 -12436,1514674927426,55 -12437,1514674971175,54 -12438,1514675018481,55 -12439,1514675058618,55 -12440,1514675108186,58 -12441,1514675136704,59 -12442,1514675364410,61 -12443,1514675741816,61 -12444,1514675948493,60 -12445,1514675972472,58 -12446,1514675976925,62 -12447,1514676157116,93 -12448,1514676535161,91 -12449,1514676788989,89 -12450,1514677047781,87 -12451,1514677124081,85 -12452,1514677210946,85 -12453,1514677280258,84 -12454,1514677379335,84 -12455,1514677623274,83 -12456,1514677975532,81 -12457,1514678112197,79 -12458,1514678293658,76 -12459,1514678424792,74 -12460,1514678553127,73 -12461,1514678738693,77 -12462,1514678749715,76 -12463,1514678793151,89 -12464,1514679042412,91 -12465,1514679314421,89 -12466,1514679593763,86 -12467,1514679816657,85 -12468,1514680345039,82 -12469,1514680949541,79 -12470,1514681495193,76 -12471,1514681540481,73 -12472,1514681723132,73 -12473,1514681991358,72 -12474,1514682074233,70 -12475,1514682193737,70 -12476,1514682279489,68 -12477,1514682440263,67 -12478,1514682487952,65 -12479,1514682789017,65 -12480,1514682833052,66 -12481,1514683183885,65 -12482,1514683797313,63 -12483,1514684110466,60 -12484,1514684152897,57 -12485,1514684238898,57 -12486,1514684246906,55 -12487,1514684612248,69 -12488,1514684786421,69 -12489,1514685015712,68 -12490,1514685168137,69 -12491,1514685425100,67 -12492,1514685579632,65 -12493,1514685601212,63 -12494,1514685633485,67 -12495,1514686322026,70 -12496,1514687437036,67 -12497,1514688630669,64 -12498,1514688694483,60 -12499,1514688771126,59 -12500,1514688793353,62 -12501,1514688951742,65 -12502,1514689290646,62 -12503,1514689653471,62 -12504,1514689681081,61 -12505,1514689785666,63 -12506,1514689901207,61 -12507,1514690007122,59 -12508,1514690394889,58 -12509,1514690406763,54 -12510,1514690428411,63 -12511,1514690491263,67 -12512,1514690623249,68 -12513,1514690776731,66 -12514,1514690859533,64 -12515,1514691236294,62 -12516,1514691407430,58 -12517,1514691574703,56 -12518,1514691686847,54 -12519,1514691750576,51 -12520,1514691783807,49 -12521,1514691808802,48 -12522,1514691850610,51 -12523,1514691898537,51 -12524,1514691953115,60 -12525,1514692205932,59 -12526,1514692233025,56 -12527,1514692268576,58 -12528,1514692310898,58 -12529,1514692363811,58 -12530,1514692377910,58 -12531,1514692471181,64 -12532,1514692676072,62 -12533,1514692882789,59 -12534,1514693018162,58 -12535,1514693140460,57 -12536,1514693182097,55 -12537,1514693209128,54 -12538,1514693366275,57 -12539,1514693528944,55 -12540,1514693593876,53 -12541,1514693681924,52 -12542,1514693898248,52 -12543,1514694335083,50 -12544,1514694401459,46 -12545,1514694406047,44 -12546,1514694648038,66 -12547,1514694912057,80 -12548,1514694950706,78 -12549,1514695033191,80 -12550,1514695062317,78 -12551,1514695335097,82 -12552,1514695536244,80 -12553,1514695808479,78 -12554,1514695852887,77 -12555,1514696007892,77 -12556,1514696048240,75 -12557,1514696179082,77 -12558,1514696341194,75 -12559,1514696509315,72 -12560,1514696565989,70 -12561,1514697073454,70 -12562,1514697255357,67 -12563,1514697749208,72 -12564,1514697823715,72 -12565,1514697955764,71 -12566,1514698202520,70 -12567,1514698455444,67 -12568,1514698839126,64 -12569,1514699026277,61 -12570,1514699176096,59 -12571,1514699336720,56 -12572,1514699360979,56 -12573,1514699544912,58 -12574,1514699578884,55 -12575,1514699616374,56 -12576,1514699742952,57 -12577,1514699865744,55 -12578,1514700057784,53 -12579,1514700198712,52 -12580,1514700303720,49 -12581,1514700324727,49 -12582,1514700375085,51 -12583,1514700392772,50 -12584,1514700439446,53 -12585,1514700591298,53 -12586,1514700768197,51 -12587,1514700882557,57 -12588,1514701155929,54 -12589,1514701218357,52 -12590,1514701436348,51 -12591,1514701646331,48 -12592,1514701680437,45 -12593,1514701743307,46 -12594,1514701823268,47 -12595,1514702090569,48 -12596,1514702232092,45 -12597,1514702392384,43 -12598,1514702492200,40 -12599,1514702506176,38 -12600,1514702793083,42 -12601,1514703107989,43 -12602,1514703143729,40 -12603,1514703172024,40 -12604,1514703183997,40 -12605,1514703383793,46 -12606,1514703395274,44 -12607,1514703423447,51 -12608,1514703558427,53 -12609,1514703913314,49 -12610,1514703927419,52 -12611,1514704039074,60 -12612,1514704062939,60 -12613,1514704083434,62 -12614,1514704214763,67 -12615,1514704228648,65 -12616,1514704297289,73 -12617,1514704588308,72 -12618,1514704904428,69 -12619,1514705161152,67 -12620,1514705254407,64 -12621,1514705271420,63 -12622,1514705421122,71 -12623,1514705745721,70 -12624,1514706036554,68 -12625,1514706467783,66 -12626,1514706816714,62 -12627,1514706943249,61 -12628,1514706950887,60 -12629,1514707031437,78 -12630,1514707135116,78 -12631,1514707228642,81 -12632,1514707318409,80 -12633,1514707741993,78 -12634,1514708302999,75 -12635,1514708408077,72 -12636,1514708416122,71 -12637,1514708477771,90 -12638,1514708815391,92 -12639,1514708968725,88 -12640,1514709068882,86 -12641,1514709073314,85 -12642,1514709153830,128 -12643,1514709194739,128 -12644,1514709463930,130 -12645,1514710826499,127 -12646,1514712194261,134 -12647,1514712442063,130 -12648,1514712446546,128 -12649,1514712916556,194 -12650,1514713145902,190 -12651,1514713500316,190 -12652,1514714376809,186 -12653,1514714473190,182 -12654,1514715686797,181 -12655,1514715969981,179 -12656,1514716478796,175 -12657,1514716939937,173 -12658,1514718626234,169 -12659,1514718956219,164 -12660,1514719313927,160 -12661,1514719385550,157 -12662,1514719482074,157 -12663,1514719898571,156 -12664,1514721256622,152 -12665,1514721260826,148 -12666,1514721382539,227 -12667,1514722029046,226 -12668,1514723869500,220 -12669,1514723965231,214 -12670,1514724233656,213 -12671,1514724630018,208 -12672,1514724793725,203 -12673,1514724858491,202 -12674,1514725234660,203 -12675,1514725404690,200 -12676,1514725408965,197 -12677,1514725524401,302 -12678,1514725614045,300 -12679,1514725843041,299 -12680,1514726184228,295 -12681,1514726500436,288 -12682,1514727401685,285 -12683,1514727531764,277 -12684,1514728005788,277 -12685,1514729023495,271 -12686,1514729382140,264 -12687,1514729868713,257 -12688,1514730036154,251 -12689,1514730089565,246 -12690,1514731639321,249 -12691,1514733225566,240 -12692,1514734925465,233 -12693,1514735166328,225 -12694,1514735370208,220 -12695,1514735627518,214 -12696,1514735694944,208 -12697,1514735790703,207 -12698,1514736342683,204 -12699,1514736497456,196 -12700,1514736919695,194 -12701,1514737803919,185 -12702,1514737915077,177 -12703,1514737994441,173 -12704,1514738099875,172 -12705,1514738344593,170 -12706,1514738691942,163 -12707,1514739160070,160 -12708,1514739610208,154 -12709,1514739693720,147 -12710,1514740064952,142 -12711,1514740144545,139 -12712,1514740326178,135 -12713,1514740559264,131 -12714,1514740767448,128 -12715,1514740997922,121 -12716,1514741362780,119 -12717,1514741586908,113 -12718,1514742068254,106 -12719,1514742603515,98 -12720,1514742702660,90 -12721,1514742889281,84 -12722,1514742929666,82 -12723,1514743036919,79 -12724,1514743205010,72 -12725,1514743229090,66 -12726,1514743273934,64 -12727,1514743564933,59 -12728,1514743605509,52 -12729,1514743636035,56 -12730,1514743697700,53 -12731,1514743860467,48 -12732,1514744056119,41 -12733,1514744309378,34 -12734,1514744321036,26 -12735,1514744366896,24 -12736,1514744380799,18 -12737,1514744391875,23 -12738,1514744396040,22 -12739,1514744400370,26 -12740,1514744411129,33 -12741,1514744431701,33 -12742,1514744456986,52 -12743,1514744540120,51 -12744,1514744577921,48 -12745,1514744809614,44 -12746,1514744826766,37 -12747,1514744971782,34 -12748,1514744982669,28 -12749,1514745010666,61 -12750,1514745024673,59 -12751,1514745052745,63 -12752,1514745187458,62 -12753,1514745371392,57 -12754,1514745524279,52 -12755,1514745730629,45 -12756,1514745788637,40 -12757,1514745829076,34 -12758,1514745865745,30 -12759,1514745880008,25 -12760,1514745939127,22 -12761,1514746010125,17 -12762,1514746126261,12 -12763,1514746166483,7 -12764,1514746227980,1 -12765,1514746232473,1 -12766,1514746244683,30 -12767,1514746335124,33 -12768,1514746500513,28 -12769,1514746537404,23 -12770,1514746614955,21 -12771,1514746623030,17 -12772,1514746673712,16 -12773,1514746738511,13 -12774,1514746742783,12 -12775,1514746746922,13 -12776,1514746834100,16 -12777,1514746870970,68 -12778,1514746895567,71 -12779,1514747601632,78 -12780,1514747698171,75 -12781,1514747862377,74 -12782,1514748047321,72 -12783,1514748104959,70 -12784,1514748112639,71 -12785,1514748146368,89 -12786,1514748425048,92 -12787,1514748501694,89 -12788,1514748898089,88 -12789,1514749249878,85 -12790,1514749583742,87 -12791,1514749643384,84 -12792,1514749660449,83 -12793,1514749854031,91 -12794,1514750350644,89 -12795,1514750404158,85 -12796,1514750488298,85 -12797,1514750945236,87 -12798,1514751151714,86 -12799,1514751418028,83 -12800,1514751567639,81 -12801,1514751578555,78 -12802,1514751810610,92 -12803,1514752107223,89 -12804,1514752430838,89 -12805,1514752724282,87 -12806,1514753052671,84 -12807,1514753519536,81 -12808,1514753543723,77 -12809,1514753701247,80 -12810,1514753862037,79 -12811,1514754720414,77 -12812,1514754916488,74 -12813,1514755279857,72 -12814,1514755585702,68 -12815,1514756013973,65 -12816,1514756327490,62 -12817,1514756368074,59 -12818,1514756492615,58 -12819,1514756727678,55 -12820,1514756732004,51 -12821,1514756821731,77 -12822,1514756829780,74 -12823,1514756844021,94 -12824,1514756963902,106 -12825,1514758049879,103 -12826,1514759482991,101 -12827,1514759676365,99 -12828,1514759729783,95 -12829,1514759880950,96 -12830,1514759892705,94 -12831,1514759907759,108 -12832,1514760090148,121 -12833,1514760143787,117 -12834,1514760275514,117 -12835,1514760462065,116 -12836,1514760560894,112 -12837,1514760715404,111 -12838,1514760825926,109 -12839,1514760900111,113 -12840,1514760998547,119 -12841,1514761685559,120 -12842,1514762402662,117 -12843,1514762766486,115 -12844,1514762774512,111 -12845,1514763455087,140 -12846,1514763679800,135 -12847,1514763867389,134 -12848,1514764136211,130 -12849,1514764420211,130 -12850,1514764460617,127 -12851,1514764547554,135 -12852,1514764739937,136 -12853,1514764771271,133 -12854,1514765030621,139 -12855,1514765070435,135 -12856,1514765120419,137 -12857,1514765475339,139 -12858,1514765924369,136 -12859,1514766127656,132 -12860,1514766407434,129 -12861,1514766749211,125 -12862,1514766819373,121 -12863,1514766884584,120 -12864,1514767262686,118 -12865,1514767452717,113 -12866,1514767891365,109 -12867,1514768467945,107 -12868,1514768681589,102 -12869,1514769213855,98 -12870,1514769739359,93 -12871,1514770111395,89 -12872,1514770525485,87 -12873,1514770780068,81 -12874,1514770942046,77 -12875,1514771004854,75 -12876,1514771145761,77 -12877,1514771437501,73 -12878,1514771783658,70 -12879,1514771937932,69 -12880,1514771991523,65 -12881,1514772101962,63 -12882,1514772122419,60 -12883,1514772328962,62 -12884,1514772392909,59 -12885,1514772530431,67 -12886,1514772551023,66 -12887,1514772578111,70 -12888,1514773095296,73 -12889,1514773950976,67 -12890,1514773958777,63 -12891,1514774126997,77 -12892,1514774375389,75 -12893,1514774621052,76 -12894,1514774799212,73 -12895,1514774886445,68 -12896,1514774979894,66 -12897,1514775003547,64 -12898,1514775040520,65 -12899,1514775051270,66 -12900,1514775161702,75 -12901,1514775207453,71 -12902,1514775602993,79 -12903,1514776158712,74 -12904,1514776270123,69 -12905,1514776401884,66 -12906,1514776448617,62 -12907,1514776466161,60 -12908,1514776487054,63 -12909,1514776504391,69 -12910,1514776574403,73 -12911,1514776712460,71 -12912,1514776736129,66 -12913,1514776766750,68 -12914,1514776777183,68 -12915,1514777013476,78 -12916,1514777043617,73 -12917,1514777186226,72 -12918,1514777657633,70 -12919,1514777718165,64 -12920,1514777997387,61 -12921,1514778034152,70 -12922,1514778196206,70 -12923,1514778381268,76 -12924,1514779184084,80 -12925,1514779365990,77 -12926,1514779608342,72 -12927,1514779864605,68 -12928,1514779921561,64 -12929,1514779960985,64 -12930,1514780008028,63 -12931,1514780184037,71 -12932,1514780270958,75 -12933,1514780757081,73 -12934,1514780890748,72 -12935,1514780953494,70 -12936,1514781020347,69 -12937,1514781144071,68 -12938,1514781242382,65 -12939,1514781442420,63 -12940,1514781548173,61 -12941,1514781672271,60 -12942,1514781900215,56 -12943,1514781910973,53 -12944,1514782242369,60 -12945,1514782266362,72 -12946,1514782469680,75 -12947,1514782541698,74 -12948,1514782726119,71 -12949,1514782878511,69 -12950,1514782906386,67 -12951,1514782985825,72 -12952,1514783056850,72 -12953,1514783145327,71 -12954,1514783264673,73 -12955,1514783363948,72 -12956,1514783490741,73 -12957,1514783791737,74 -12958,1514783890261,70 -12959,1514784125595,69 -12960,1514784140180,66 -12961,1514784187256,74 -12962,1514784505881,74 -12963,1514784783470,72 -12964,1514785013847,71 -12965,1514785420723,67 -12966,1514785908668,64 -12967,1514786226234,61 -12968,1514786233981,58 -12969,1514786315431,72 -12970,1514786375716,70 -12971,1514786478303,68 -12972,1514786742982,66 -12973,1514786813296,63 -12974,1514787206623,61 -12975,1514787681379,58 -12976,1514787688793,55 -12977,1514787726716,68 -12978,1514787996872,69 -12979,1514788027375,65 -12980,1514788246405,66 -12981,1514788448331,63 -12982,1514788488118,60 -12983,1514788518733,63 -12984,1514788642153,63 -12985,1514788666083,60 -12986,1514788683165,63 -12987,1514788701421,71 -12988,1514788998359,79 -12989,1514789029618,74 -12990,1514789080380,76 -12991,1514789136556,84 -12992,1514789291338,84 -12993,1514789469960,80 -12994,1514789557097,77 -12995,1514789597349,75 -12996,1514790091150,75 -12997,1514790105502,72 -12998,1514790341389,83 -12999,1514790352073,81 -13000,1514790415011,102 -13001,1514790422667,101 -13002,1514790596600,130 -13003,1514790620039,127 -13004,1514790890121,134 -13005,1514790977763,131 -13006,1514791201922,129 -13007,1514791272252,127 -13008,1514791631120,130 -13009,1514791940247,129 -13010,1514792291069,130 -13011,1514792398170,126 -13012,1514792543614,124 -13013,1514792587895,125 -13014,1514792651147,129 -13015,1514792998961,137 -13016,1514793047046,133 -13017,1514793118304,138 -13018,1514793361280,138 -13019,1514793613639,134 -13020,1514793645344,132 -13021,1514793716964,137 -13022,1514793973207,139 -13023,1514795049285,135 -13024,1514795181723,131 -13025,1514795624004,128 -13026,1514796160113,124 -13027,1514796528747,119 -13028,1514796532950,115 -13029,1514796547249,177 -13030,1514796611214,203 -13031,1514796809790,205 -13032,1514797068698,202 -13033,1514798040753,198 -13034,1514798287216,192 -13035,1514798723953,187 -13036,1514798851909,183 -13037,1514799373703,181 -13038,1514800024574,176 -13039,1514800268291,170 -13040,1514800762159,166 -13041,1514800942591,161 -13042,1514800946834,156 -13043,1514801501491,238 -13044,1514802684839,238 -13045,1514802757048,231 -13046,1514803003923,233 -13047,1514803700690,229 -13048,1514803796528,223 -13049,1514803875374,221 -13050,1514803993594,220 -13051,1514804051931,219 -13052,1514804260289,221 -13053,1514804346565,217 -13054,1514804562707,217 -13055,1514804971745,211 -13056,1514805134243,205 -13057,1514805155415,201 -13058,1514805409913,215 -13059,1514805768589,210 -13060,1514806330682,203 -13061,1514806416969,201 -13062,1514806476490,200 -13063,1514806653091,200 -13064,1514806758433,195 -13065,1514807405959,190 -13066,1514808331623,183 -13067,1514808714048,174 -13068,1514808837801,167 -13069,1514809391297,171 -13070,1514810460372,165 -13071,1514810757889,158 -13072,1514811243469,151 -13073,1514811643732,145 -13074,1514811831828,137 -13075,1514811932370,131 -13076,1514812148415,126 -13077,1514812643374,129 -13078,1514813327497,123 -13079,1514813404485,116 -13080,1514813661628,114 -13081,1514813688807,107 -13082,1514814282948,109 -13083,1514814472539,103 -13084,1514814661558,99 -13085,1514814747808,93 -13086,1514814939491,90 -13087,1514814983517,88 -13088,1514815378153,90 -13089,1514815779680,83 -13090,1514816190791,78 -13091,1514816263647,73 -13092,1514816369238,69 -13093,1514816384365,63 -13094,1514816749378,67 -13095,1514816813179,60 -13096,1514816861804,56 -13097,1514816873184,51 -13098,1514816970536,60 -13099,1514817039756,55 -13100,1514817129582,58 -13101,1514817192231,54 -13102,1514817510303,65 -13103,1514817712517,60 -13104,1514817833917,59 -13105,1514817987634,54 -13106,1514818060865,50 -13107,1514818123654,45 -13108,1514818209638,43 -13109,1514818386930,38 -13110,1514818553579,32 -13111,1514818691510,25 -13112,1514818864194,21 -13113,1514818908764,15 -13114,1514818924075,12 -13115,1514818962253,11 -13116,1514819028645,5 -13117,1514819096777,2 -13118,1514819115276,1 -13119,1514819119680,1 -13120,1514819131555,1 -13121,1514819139467,1 -13122,1514819151473,1 -13123,1514819160246,1 -13124,1514819168910,1 -13125,1514819176346,1 -13126,1514819180615,1 -13127,1514819185383,1 -13128,1514819189805,1 -13129,1514819198985,1 -13130,1514819203157,1 -13131,1514819210594,1 -13132,1514819215194,1 -13133,1514819223938,1 -13134,1514819231975,1 -13135,1514819236235,1 -13136,1514819240722,1 -13137,1514819249283,1 -13138,1514819261441,1 -13139,1514819265828,1 -13140,1514819270135,1 -13141,1514819274761,1 -13142,1514819286633,1 -13143,1514819295104,1 -13144,1514819299358,1 -13145,1514819307147,1 -13146,1514819311439,1 -13147,1514819315564,1 -13148,1514819323139,1 -13149,1514819331942,1 -13150,1514819336242,1 -13151,1514819340650,1 -13152,1514819349256,1 -13153,1514819361449,1 -13154,1514819370174,1 -13155,1514819377782,1 -13156,1514819382173,1 -13157,1514819386403,1 -13158,1514819390872,1 -13159,1514819399333,1 -13160,1514819403826,1 -13161,1514819412978,1 -13162,1514819422053,1 -13163,1514819430902,1 -13164,1514819443236,1 -13165,1514819451719,1 -13166,1514819456035,1 -13167,1514819460574,1 -13168,1514819465039,1 -13169,1514819472764,1 -13170,1514819477177,1 -13171,1514819481403,1 -13172,1514819485903,1 -13173,1514819494419,1 -13174,1514819498707,1 -13175,1514819503184,1 -13176,1514819508016,1 -13177,1514819512354,1 -13178,1514819520963,1 -13179,1514819525475,1 -13180,1514819529717,1 -13181,1514819534111,1 -13182,1514819538449,1 -13183,1514819546139,1 -13184,1514819550441,1 -13185,1514819554650,1 -13186,1514819558980,1 -13187,1514819563282,1 -13188,1514819567545,1 -13189,1514819571887,1 -13190,1514819576057,1 -13191,1514819584564,1 -13192,1514819588772,1 -13193,1514819593302,1 -13194,1514819601821,1 -13195,1514819610386,1 -13196,1514819615230,1 -13197,1514819623859,2 -13198,1514819632963,6 -13199,1514819640402,8 -13200,1514819658155,11 -13201,1514819715238,13 -13202,1514819719617,13 -13203,1514819738357,20 -13204,1514819815486,22 -13205,1514819823050,22 -13206,1514819905542,28 -13207,1514819929361,29 -13208,1514820002617,32 -13209,1514820036237,32 -13210,1514820093827,35 -13211,1514820154309,35 -13212,1514820249359,36 -13213,1514820305766,35 -13214,1514820342601,36 -13215,1514820428847,38 -13216,1514820534992,38 -13217,1514820545934,39 -13218,1514820590602,46 -13219,1514820719032,47 -13220,1514820876917,47 -13221,1514821031304,46 -13222,1514821231477,46 -13223,1514821488005,45 -13224,1514821518425,45 -13225,1514821591162,48 -13226,1514821598931,47 -13227,1514821666164,61 -13228,1514821696788,62 -13229,1514822263016,65 -13230,1514822448272,64 -13231,1514822674687,64 -13232,1514822698563,63 -13233,1514823179011,67 -13234,1514823885208,66 -13235,1514824175442,65 -13236,1514824269907,64 -13237,1514824422166,64 -13238,1514824678446,63 -13239,1514824810598,62 -13240,1514824888026,62 -13241,1514825199169,62 -13242,1514825236924,61 -13243,1514825247858,64 -13244,1514825350589,76 -13245,1514825354975,76 -13246,1514825776102,115 -13247,1514825845627,113 -13248,1514825958086,115 -13249,1514826139360,114 -13250,1514826509220,114 -13251,1514826886010,111 -13252,1514827010284,110 -13253,1514827206076,109 -13254,1514827454169,108 -13255,1514827478283,106 -13256,1514827557958,114 -13257,1514827710522,114 -13258,1514828123840,113 -13259,1514828306668,111 -13260,1514828317793,110 -13261,1514828485695,130 -13262,1514828683200,129 -13263,1514828783130,127 -13264,1514828836896,126 -13265,1514829146090,129 -13266,1514829231442,126 -13267,1514829291926,126 -13268,1514829365996,128 -13269,1514829384233,129 -13270,1514829659582,142 -13271,1514830105991,140 -13272,1514830803508,136 -13273,1514831208951,133 -13274,1514831240419,130 -13275,1514831321456,135 -13276,1514831406848,135 -13277,1514831476801,135 -13278,1514831559655,135 -13279,1514831808203,135 -13280,1514831838789,133 -13281,1514831943840,138 -13282,1514832208968,138 -13283,1514832558560,135 -13284,1514832663883,130 -13285,1514832832276,129 -13286,1514832836685,127 -13287,1514833492861,191 -13288,1514833624287,187 -13289,1514833935297,184 -13290,1514833952691,180 -13291,1514834129122,200 -13292,1514834245140,196 -13293,1514834628895,194 -13294,1514834759954,190 -13295,1514835548687,187 -13296,1514835682892,181 -13297,1514836226119,179 -13298,1514837288297,173 -13299,1514837508251,168 -13300,1514838913701,165 -13301,1514838937811,159 -13302,1514839634617,169 -13303,1514839713593,166 -13304,1514839819725,167 -13305,1514839975080,164 -13306,1514840638062,163 -13307,1514841250749,158 -13308,1514841439288,153 -13309,1514841765912,150 -13310,1514842148948,145 -13311,1514842216316,141 -13312,1514842436566,140 -13313,1514842748707,135 -13314,1514842766338,130 -13315,1514842951477,143 -13316,1514843208133,139 -13317,1514843913060,133 -13318,1514843954164,131 -13319,1514844382112,134 -13320,1514844655587,128 -13321,1514845007094,123 -13322,1514845101286,118 -13323,1514845273506,114 -13324,1514845797798,109 -13325,1514846224576,105 -13326,1514846275033,99 -13327,1514846362469,105 -13328,1514846418272,102 -13329,1514846561392,102 -13330,1514846610763,98 -13331,1514846828676,97 -13332,1514847310623,91 -13333,1514847779683,88 -13334,1514847903921,82 -13335,1514848154868,77 -13336,1514848192285,71 -13337,1514848352966,70 -13338,1514848512965,65 -13339,1514848567893,60 -13340,1514848638630,57 -13341,1514848692261,53 -13342,1514848749562,48 -13343,1514848820261,46 -13344,1514848870616,48 -13345,1514848937847,45 -13346,1514849286727,62 -13347,1514849914725,56 -13348,1514849961276,53 -13349,1514850093921,51 -13350,1514850101814,46 -13351,1514850205299,55 -13352,1514850236091,51 -13353,1514850360373,50 -13354,1514850374688,45 -13355,1514850460149,47 -13356,1514850590155,48 -13357,1514850630092,44 -13358,1514850699088,42 -13359,1514850836102,38 -13360,1514850851505,33 -13361,1514850917935,45 -13362,1514850989916,42 -13363,1514851126905,38 -13364,1514851151104,34 -13365,1514851162037,35 -13366,1514851205615,37 -13367,1514851288786,36 -13368,1514851378644,34 -13369,1514851424858,31 -13370,1514851438780,36 -13371,1514851443127,37 -13372,1514851483960,52 -13373,1514851600301,50 -13374,1514851690305,46 -13375,1514851875494,46 -13376,1514852017953,43 -13377,1514852095337,40 -13378,1514852274837,39 -13379,1514852341676,35 -13380,1514852421971,31 -13381,1514852463998,33 -13382,1514852504208,31 -13383,1514852557349,28 -13384,1514852587788,25 -13385,1514852602292,22 -13386,1514852609901,22 -13387,1514852620629,59 -13388,1514852671679,68 -13389,1514852848024,69 -13390,1514852911859,65 -13391,1514852988271,76 -13392,1514853088904,76 -13393,1514853490774,76 -13394,1514853514313,72 -13395,1514853710088,77 -13396,1514853730814,74 -13397,1514853751877,81 -13398,1514854052479,86 -13399,1514854099230,82 -13400,1514854237767,82 -13401,1514854479239,80 -13402,1514854599839,84 -13403,1514854637980,82 -13404,1514854733404,85 -13405,1514855390643,85 -13406,1514855440249,82 -13407,1514855595067,82 -13408,1514856037714,80 -13409,1514856120585,76 -13410,1514856337482,75 -13411,1514856486670,73 -13412,1514856510504,72 -13413,1514856775018,75 -13414,1514857078782,73 -13415,1514857268311,78 -13416,1514857379740,75 -13417,1514857463960,74 -13418,1514857580519,72 -13419,1514857601196,74 -13420,1514857771683,79 -13421,1514857785874,77 -13422,1514857992701,85 -13423,1514858063349,84 -13424,1514858511975,83 -13425,1514858783841,80 -13426,1514858808165,77 -13427,1514859094280,82 -13428,1514859161057,80 -13429,1514859308200,81 -13430,1514859480494,78 -13431,1514859525008,78 -13432,1514859553952,78 -13433,1514859585118,81 -13434,1514859845420,83 -13435,1514860127805,80 -13436,1514860175243,77 -13437,1514860195863,78 -13438,1514860200183,84 -13439,1514860264222,126 -13440,1514860308180,127 -13441,1514860360180,131 -13442,1514860412572,133 -13443,1514860571839,134 -13444,1514860919878,132 -13445,1514861323831,128 -13446,1514861598324,124 -13447,1514861863892,120 -13448,1514862202035,116 -13449,1514862357391,113 -13450,1514862433359,110 -13451,1514862639187,115 -13452,1514863160243,112 -13453,1514863872112,108 -13454,1514864081559,104 -13455,1514864435848,105 -13456,1514864492884,101 -13457,1514864598527,100 -13458,1514864678455,99 -13459,1514864789676,97 -13460,1514865116990,94 -13461,1514865661408,92 -13462,1514865998865,88 -13463,1514866240911,85 -13464,1514866392568,81 -13465,1514866922944,79 -13466,1514867321683,78 -13467,1514867413412,75 -13468,1514867513009,72 -13469,1514867682021,70 -13470,1514867784469,66 -13471,1514868065150,66 -13472,1514868439955,72 -13473,1514868595499,70 -13474,1514869187678,67 -13475,1514869757861,63 -13476,1514869771797,60 -13477,1514869822916,66 -13478,1514869827248,65 -13479,1514869838392,96 -13480,1514870024911,112 -13481,1514870072032,109 -13482,1514870188119,110 -13483,1514870623634,107 -13484,1514870860171,103 -13485,1514871234747,100 -13486,1514871852119,97 -13487,1514872554288,96 -13488,1514872688111,97 -13489,1514872722331,95 -13490,1514872726741,97 -13491,1514872754908,146 -13492,1514872803285,154 -13493,1514873358337,155 -13494,1514874355867,150 -13495,1514874380211,148 -13496,1514874578031,157 -13497,1514874959215,157 -13498,1514875445782,157 -13499,1514876013661,151 -13500,1514876034405,148 -13501,1514876257187,160 -13502,1514877117700,156 -13503,1514877319535,150 -13504,1514877820811,148 -13505,1514878127627,144 -13506,1514878355376,138 -13507,1514878467723,136 -13508,1514878853961,133 -13509,1514879243041,128 -13510,1514879838552,124 -13511,1514880042451,118 -13512,1514880046808,114 -13513,1514880367202,174 -13514,1514880413732,169 -13515,1514880500833,171 -13516,1514880594958,169 -13517,1514880619226,167 -13518,1514881656292,177 -13519,1514882783100,171 -13520,1514883228930,168 -13521,1514883775737,162 -13522,1514884578259,162 -13523,1514885796154,156 -13524,1514885961887,150 -13525,1514886430295,146 -13526,1514886602823,140 -13527,1514887286661,138 -13528,1514887824552,131 -13529,1514888261799,127 -13530,1514889149583,121 -13531,1514890056120,115 -13532,1514890139605,110 -13533,1514890384342,110 -13534,1514890663359,108 -13535,1514891112970,102 -13536,1514891401085,96 -13537,1514891809747,91 -13538,1514892160958,90 -13539,1514892618791,108 -13540,1514892669036,105 -13541,1514893465113,107 -13542,1514893524859,105 -13543,1514893685364,106 -13544,1514893784604,104 -13545,1514894233051,101 -13546,1514894749132,96 -13547,1514894967037,91 -13548,1514895000785,87 -13549,1514895047939,87 -13550,1514895055601,87 -13551,1514895084094,110 -13552,1514895113017,114 -13553,1514895278446,117 -13554,1514895547554,112 -13555,1514896334202,107 -13556,1514896824465,101 -13557,1514896862428,98 -13558,1514897152654,99 -13559,1514897170153,95 -13560,1514897198310,102 -13561,1514897487466,104 -13562,1514897501561,99 -13563,1514897505931,109 -13564,1514897549174,162 -13565,1514897556802,164 -13566,1514898026219,208 -13567,1514898161047,200 -13568,1514898206322,196 -13569,1514898317979,198 -13570,1514899787573,194 -13571,1514900030127,186 -13572,1514901159131,180 -13573,1514901388756,171 -13574,1514901590973,164 -13575,1514901892696,157 -13576,1514901966370,150 -13577,1514903726746,150 -13578,1514905622175,143 -13579,1514905685418,153 -13580,1514906177337,161 -13581,1514906288728,155 -13582,1514906494904,153 -13583,1514906577399,148 -13584,1514906780793,143 -13585,1514906985213,138 -13586,1514907368382,131 -13587,1514907789485,125 -13588,1514907891568,117 -13589,1514908296494,112 -13590,1514908884331,108 -13591,1514909248522,128 -13592,1514909252995,128 -13593,1514909435684,193 -13594,1514909646557,188 -13595,1514909869666,181 -13596,1514910583074,183 -13597,1514911628809,177 -13598,1514911983754,170 -13599,1514911994470,163 -13600,1514912210410,192 -13601,1514912465923,195 -13602,1514912750168,189 -13603,1514912872206,183 -13604,1514912965397,179 -13605,1514913346767,175 -13606,1514914125074,169 -13607,1514914711292,162 -13608,1514915070955,155 -13609,1514915130085,148 -13610,1514915660993,146 -13611,1514916191860,138 -13612,1514916212710,132 -13613,1514916515136,171 -13614,1514916583685,165 -13615,1514916716534,168 -13616,1514917195981,166 -13617,1514918251304,161 -13618,1514918315058,163 -13619,1514918442898,162 -13620,1514918584302,157 -13621,1514918885676,153 -13622,1514918960962,147 -13623,1514919773961,145 -13624,1514920890096,137 -13625,1514921208208,131 -13626,1514921347547,125 -13627,1514921578195,121 -13628,1514921749386,114 -13629,1514921841588,109 -13630,1514922233959,104 -13631,1514922241876,98 -13632,1514922261297,120 -13633,1514922286738,128 -13634,1514922855266,132 -13635,1514922908781,126 -13636,1514923248978,123 -13637,1514923372484,116 -13638,1514923734851,110 -13639,1514924317021,103 -13640,1514924570823,95 -13641,1514924948320,90 -13642,1514925426025,82 -13643,1514925611710,76 -13644,1514925658699,70 -13645,1514925732013,67 -13646,1514925805181,61 -13647,1514925899954,54 -13648,1514925927190,48 -13649,1514925955059,47 -13650,1514925959352,44 -13651,1514926162764,75 -13652,1514926477682,72 -13653,1514926904044,69 -13654,1514927079667,62 -13655,1514927103747,56 -13656,1514927179618,54 -13657,1514927259404,47 -13658,1514927486424,44 -13659,1514927560749,37 -13660,1514927671027,36 -13661,1514927678393,34 -13662,1514927708634,38 -13663,1514927809412,41 -13664,1514928001036,65 -13665,1514928065283,64 -13666,1514928188788,86 -13667,1514928274446,83 -13668,1514928600101,81 -13669,1514928966909,81 -13670,1514929092850,78 -13671,1514929129735,73 -13672,1514929274795,74 -13673,1514929343968,69 -13674,1514929465300,66 -13675,1514929486720,63 -13676,1514929655292,65 -13677,1514929666106,62 -13678,1514929903451,70 -13679,1514930230381,65 -13680,1514930450793,62 -13681,1514930478289,57 -13682,1514930512105,58 -13683,1514930628429,56 -13684,1514930732597,55 -13685,1514930813282,51 -13686,1514930937450,47 -13687,1514930958003,42 -13688,1514931132835,41 -13689,1514931202053,37 -13690,1514931294375,32 -13691,1514931338406,28 -13692,1514931455073,23 -13693,1514931600772,54 -13694,1514931624663,51 -13695,1514931642761,51 -13696,1514931883388,55 -13697,1514932259254,51 -13698,1514932385497,46 -13699,1514932553828,42 -13700,1514932594104,56 -13701,1514932638415,56 -13702,1514932825475,56 -13703,1514933295371,53 -13704,1514933460461,51 -13705,1514933701538,49 -13706,1514933728954,45 -13707,1514933884978,45 -13708,1514933899456,42 -13709,1514933914313,45 -13710,1514934104672,50 -13711,1514934333520,47 -13712,1514934703996,43 -13713,1514935111511,46 -13714,1514935119060,43 -13715,1514935197401,56 -13716,1514935421933,54 -13717,1514935649180,51 -13718,1514935673421,47 -13719,1514935805020,50 -13720,1514935812896,48 -13721,1514935852084,59 -13722,1514936012115,59 -13723,1514936033006,58 -13724,1514936056805,60 -13725,1514936081165,62 -13726,1514936112720,63 -13727,1514936176358,65 -13728,1514936715551,63 -13729,1514936739308,59 -13730,1514936934924,62 -13731,1514937073417,58 -13732,1514937188573,69 -13733,1514937193734,73 -13734,1514937227517,109 -13735,1514937326344,113 -13736,1514937590602,114 -13737,1514937608366,111 -13738,1514937626383,122 -13739,1514937773861,134 -13740,1514938201121,131 -13741,1514938700096,127 -13742,1514938759533,122 -13743,1514938953128,123 -13744,1514939183400,120 -13745,1514939236250,117 -13746,1514939253489,119 -13747,1514939377334,132 -13748,1514939618703,129 -13749,1514939781564,127 -13750,1514940447581,126 -13751,1514941512176,133 -13752,1514942384068,129 -13753,1514942440839,125 -13754,1514942484176,125 -13755,1514942562269,128 -13756,1514943137057,129 -13757,1514943237674,125 -13758,1514943389757,124 -13759,1514943744723,121 -13760,1514944231907,117 -13761,1514944278774,112 -13762,1514944469445,119 -13763,1514944666098,117 -13764,1514944827344,114 -13765,1514945255514,111 -13766,1514945659868,108 -13767,1514945696808,104 -13768,1514945867892,107 -13769,1514946064266,103 -13770,1514946310677,100 -13771,1514946340904,97 -13772,1514946484573,101 -13773,1514947384309,99 -13774,1514947683648,95 -13775,1514948162898,91 -13776,1514948440590,90 -13777,1514948628922,86 -13778,1514948764453,89 -13779,1514948979428,87 -13780,1514949179839,83 -13781,1514949221060,79 -13782,1514949301299,82 -13783,1514949645283,81 -13784,1514950177451,78 -13785,1514950423003,74 -13786,1514950851919,70 -13787,1514950895810,66 -13788,1514951374155,67 -13789,1514951542765,64 -13790,1514951572695,61 -13791,1514951612669,61 -13792,1514951723626,61 -13793,1514951728038,57 -13794,1514951913821,83 -13795,1514952032877,82 -13796,1514952179404,82 -13797,1514952591652,78 -13798,1514952886561,74 -13799,1514953370370,70 -13800,1514953997532,66 -13801,1514954220290,62 -13802,1514954991619,59 -13803,1514955035712,55 -13804,1514955175758,52 -13805,1514955452882,49 -13806,1514955745110,44 -13807,1514955806115,41 -13808,1514955920559,39 -13809,1514956075137,37 -13810,1514956082552,36 -13811,1514956086868,44 -13812,1514956100955,63 -13813,1514956115758,69 -13814,1514956332428,74 -13815,1514957034476,76 -13816,1514957607771,72 -13817,1514957664949,67 -13818,1514957755050,65 -13819,1514957934173,63 -13820,1514958297622,59 -13821,1514958418150,61 -13822,1514958607079,59 -13823,1514958699827,55 -13824,1514958734156,54 -13825,1514958778876,56 -13826,1514958909807,57 -13827,1514959077654,56 -13828,1514959204978,52 -13829,1514959255174,48 -13830,1514959316841,49 -13831,1514959420823,46 -13832,1514959428370,42 -13833,1514959667119,52 -13834,1514959988109,64 -13835,1514960052208,64 -13836,1514960366812,63 -13837,1514960972595,59 -13838,1514961335888,63 -13839,1514961448337,67 -13840,1514961815732,66 -13841,1514961905858,63 -13842,1514962059790,61 -13843,1514962347979,60 -13844,1514962597482,58 -13845,1514962634404,54 -13846,1514962809073,56 -13847,1514962823184,62 -13848,1514963326591,70 -13849,1514963383021,67 -13850,1514963548177,67 -13851,1514963562249,65 -13852,1514963566410,72 -13853,1514963687038,109 -13854,1514963713920,109 -13855,1514964395164,118 -13856,1514965468678,116 -13857,1514966850214,113 -13858,1514966973974,109 -13859,1514967282537,108 -13860,1514967871695,105 -13861,1514968240907,100 -13862,1514968382523,99 -13863,1514968527227,98 -13864,1514968603514,95 -13865,1514969019019,95 -13866,1514969449613,91 -13867,1514970002447,87 -13868,1514970006749,87 -13869,1514970070819,132 -13870,1514970299938,132 -13871,1514971016228,129 -13872,1514971070246,128 -13873,1514971309826,129 -13874,1514971450436,126 -13875,1514971936124,123 -13876,1514972002878,119 -13877,1514972152741,118 -13878,1514972301848,115 -13879,1514972445261,113 -13880,1514972490181,110 -13881,1514972768184,111 -13882,1514972808452,109 -13883,1514972986530,112 -13884,1514973244382,108 -13885,1514973346181,104 -13886,1514973541137,101 -13887,1514973695027,97 -13888,1514973705803,95 -13889,1514973743682,111 -13890,1514973824639,113 -13891,1514974062214,113 -13892,1514974199697,110 -13893,1514974243518,107 -13894,1514974539170,123 -13895,1514975312828,119 -13896,1514975906128,116 -13897,1514976008236,111 -13898,1514976140708,109 -13899,1514976376559,106 -13900,1514976640664,102 -13901,1514976746895,97 -13902,1514977095941,94 -13903,1514977471053,89 -13904,1514977864132,86 -13905,1514977869124,82 -13906,1514978021930,116 -13907,1514978219022,112 -13908,1514978236439,108 -13909,1514978240547,118 -13910,1514978321634,181 -13911,1514978351569,185 -13912,1514978584919,205 -13913,1514978795896,206 -13914,1514979491577,207 -13915,1514979552402,201 -13916,1514979698699,202 -13917,1514979891663,199 -13918,1514980183597,196 -13919,1514980234548,192 -13920,1514980924856,195 -13921,1514981775468,188 -13922,1514981906256,182 -13923,1514981929817,179 -13924,1514982856858,191 -13925,1514984707543,186 -13926,1514985646412,181 -13927,1514985972482,175 -13928,1514986801733,169 -13929,1514987347032,163 -13930,1514987398621,158 -13931,1514988679272,158 -13932,1514988719541,153 -13933,1514989245301,161 -13934,1514990010956,155 -13935,1514990412830,148 -13936,1514990546978,143 -13937,1514990729123,139 -13938,1514991120911,134 -13939,1514991722880,128 -13940,1514992296430,122 -13941,1514992415957,115 -13942,1514992544361,111 -13943,1514992637189,106 -13944,1514992988337,102 -13945,1514993675521,96 -13946,1514993689765,90 -13947,1514993762512,99 -13948,1514993978933,100 -13949,1514994139197,94 -13950,1514994189003,90 -13951,1514994298182,87 -13952,1514994358713,88 -13953,1514994530044,105 -13954,1514994534206,101 -13955,1514994681728,158 -13956,1514994889267,153 -13957,1514994916915,148 -13958,1514994995252,153 -13959,1514995716427,151 -13960,1514995783440,144 -13961,1514995882114,142 -13962,1514996036242,138 -13963,1514996131963,133 -13964,1514996186379,129 -13965,1514996657174,128 -13966,1514996970480,122 -13967,1514996987452,116 -13968,1514997125184,124 -13969,1514997189769,143 -13970,1514997310151,144 -13971,1514997594794,140 -13972,1514997981253,134 -13973,1514998400079,130 -13974,1514998729503,125 -13975,1514998836426,119 -13976,1514999045724,115 -13977,1514999249518,111 -13978,1514999520230,106 -13979,1515000111875,100 -13980,1515000316259,94 -13981,1515000613134,91 -13982,1515000856456,85 -13983,1515001193959,82 -13984,1515001522533,76 -13985,1515001578932,71 -13986,1515001775547,68 -13987,1515001792996,62 -13988,1515002013851,64 -13989,1515002317462,69 -13990,1515002413198,66 -13991,1515002534765,63 -13992,1515002667516,58 -13993,1515002764936,52 -13994,1515002878628,50 -13995,1515003057695,45 -13996,1515003091582,39 -13997,1515003153064,35 -13998,1515003289688,31 -13999,1515003386354,26 -14000,1515003517704,21 -14001,1515003561358,15 -14002,1515003598670,10 -14003,1515003621520,5 -14004,1515003646601,1 -14005,1515003650954,1 -14006,1515003655366,6 -14007,1515003662802,5 -14008,1515003673565,1 -14009,1515003678257,3 -14010,1515003686915,34 -14011,1515003777836,42 -14012,1515003864748,45 -14013,1515003905119,43 -14014,1515004207473,42 -14015,1515004211886,38 -14016,1515004219534,58 -14017,1515004295119,73 -14018,1515004464545,72 -14019,1515004607756,68 -14020,1515004829818,69 -14021,1515005263272,65 -14022,1515005329860,61 -14023,1515005624867,59 -14024,1515005691149,64 -14025,1515005826685,63 -14026,1515005934214,59 -14027,1515005945566,55 -14028,1515005960107,64 -14029,1515005987913,69 -14030,1515006151319,71 -14031,1515006451541,70 -14032,1515006884660,66 -14033,1515007226936,65 -14034,1515007511333,62 -14035,1515007889225,58 -14036,1515008308582,54 -14037,1515008503243,50 -14038,1515008546405,47 -14039,1515008554041,45 -14040,1515008834219,55 -14041,1515008930597,50 -14042,1515009073155,48 -14043,1515009080725,45 -14044,1515009146607,55 -14045,1515009279549,52 -14046,1515009303934,48 -14047,1515009378566,56 -14048,1515009389247,54 -14049,1515009634249,62 -14050,1515009883418,58 -14051,1515010000313,55 -14052,1515010193571,52 -14053,1515010412908,50 -14054,1515010570000,46 -14055,1515010734691,71 -14056,1515010788829,69 -14057,1515010953457,68 -14058,1515010971077,73 -14059,1515010992381,81 -14060,1515011152160,87 -14061,1515011338925,86 -14062,1515011356400,85 -14063,1515011607730,93 -14064,1515011889130,91 -14065,1515012154242,91 -14066,1515012683523,88 -14067,1515012832545,85 -14068,1515012974429,91 -14069,1515013069095,89 -14070,1515013206910,90 -14071,1515013619638,89 -14072,1515013731829,87 -14073,1515014012494,85 -14074,1515014143028,82 -14075,1515014353737,80 -14076,1515014361217,79 -14077,1515014483216,101 -14078,1515014497329,99 -14079,1515014783597,113 -14080,1515015083887,109 -14081,1515015158562,106 -14082,1515015182091,105 -14083,1515015222057,111 -14084,1515015475642,114 -14085,1515015759946,110 -14086,1515015764420,108 -14087,1515015994779,162 -14088,1515016292445,163 -14089,1515016461600,158 -14090,1515016700144,156 -14091,1515016823594,153 -14092,1515016901286,151 -14093,1515017254973,150 -14094,1515017497026,147 -14095,1515018109828,143 -14096,1515018452502,138 -14097,1515018803908,135 -14098,1515019090496,131 -14099,1515019810949,126 -14100,1515020570605,121 -14101,1515020620410,117 -14102,1515020758825,118 -14103,1515020983517,114 -14104,1515021159651,109 -14105,1515021370330,106 -14106,1515021828645,102 -14107,1515022546198,98 -14108,1515023080787,93 -14109,1515023473358,89 -14110,1515023661105,84 -14111,1515023834561,85 -14112,1515024068958,81 -14113,1515024276226,76 -14114,1515024732054,73 -14115,1515025066783,68 -14116,1515025080910,74 -14117,1515025277478,91 -14118,1515025539818,87 -14119,1515025816423,84 -14120,1515025830981,81 -14121,1515025860317,89 -14122,1515026009529,91 -14123,1515026427956,88 -14124,1515026561126,83 -14125,1515026614517,81 -14126,1515026852412,80 -14127,1515026877228,77 -14128,1515026918739,84 -14129,1515027036265,89 -14130,1515027474477,89 -14131,1515027838000,85 -14132,1515028023763,80 -14133,1515028255680,77 -14134,1515028528924,72 -14135,1515028602414,68 -14136,1515028659036,65 -14137,1515028786528,62 -14138,1515028946408,60 -14139,1515029281074,56 -14140,1515029649839,59 -14141,1515029730051,54 -14142,1515029848593,51 -14143,1515029859138,48 -14144,1515030178080,62 -14145,1515030300501,58 -14146,1515030451505,55 -14147,1515030587411,53 -14148,1515030878154,49 -14149,1515030882831,52 -14150,1515030951357,74 -14151,1515031124808,71 -14152,1515031218038,68 -14153,1515031377521,65 -14154,1515031621834,61 -14155,1515031936983,56 -14156,1515032003728,52 -14157,1515032075921,51 -14158,1515032200002,48 -14159,1515032307123,49 -14160,1515032344008,50 -14161,1515032502891,49 -14162,1515032631132,45 -14163,1515032662199,47 -14164,1515032713697,46 -14165,1515032874622,44 -14166,1515033058123,41 -14167,1515033118886,37 -14168,1515033249901,33 -14169,1515033449722,30 -14170,1515033584070,27 -14171,1515033611030,24 -14172,1515033657913,21 -14173,1515033718791,18 -14174,1515033749442,15 -14175,1515033797120,12 -14176,1515033804612,9 -14177,1515033822503,20 -14178,1515033839930,19 -14179,1515033871161,26 -14180,1515033912895,24 -14181,1515033980045,22 -14182,1515034016700,21 -14183,1515034090738,23 -14184,1515034138451,23 -14185,1515034155662,21 -14186,1515034211556,20 -14187,1515034245366,47 -14188,1515034311965,48 -14189,1515034396283,48 -14190,1515034501929,46 -14191,1515034559525,45 -14192,1515034644949,45 -14193,1515034727638,47 -14194,1515034741630,45 -14195,1515034808107,50 -14196,1515034918568,49 -14197,1515035061475,48 -14198,1515035121422,46 -14199,1515035132152,45 -14200,1515035248031,52 -14201,1515035430451,50 -14202,1515035460479,51 -14203,1515035591865,52 -14204,1515035753721,51 -14205,1515035916767,49 -14206,1515036123319,47 -14207,1515036167164,44 -14208,1515036245214,44 -14209,1515036395816,41 -14210,1515036572630,40 -14211,1515036707896,38 -14212,1515036853036,35 -14213,1515036885438,33 -14214,1515036919404,32 -14215,1515036982644,32 -14216,1515037087754,30 -14217,1515037178942,34 -14218,1515037253360,32 -14219,1515037273935,30 -14220,1515037299128,30 -14221,1515037313892,37 -14222,1515037332830,44 -14223,1515037574584,48 -14224,1515037582461,45 -14225,1515037586729,56 -14226,1515037732433,86 -14227,1515037927432,84 -14228,1515038285371,85 -14229,1515038611315,85 -14230,1515038959682,83 -14231,1515038993720,80 -14232,1515039145126,83 -14233,1515039202097,81 -14234,1515039565336,81 -14235,1515039949551,78 -14236,1515040082655,76 -14237,1515040252120,76 -14238,1515040579916,74 -14239,1515040604180,71 -14240,1515040705507,74 -14241,1515040995084,72 -14242,1515041777685,70 -14243,1515042183130,67 -14244,1515042207310,69 -14245,1515042500883,73 -14246,1515042605927,71 -14247,1515042712538,69 -14248,1515042998813,67 -14249,1515043302104,64 -14250,1515043352004,76 -14251,1515043392949,77 -14252,1515043481503,79 -14253,1515043669622,78 -14254,1515043752368,77 -14255,1515043929575,75 -14256,1515044059581,73 -14257,1515044146250,73 -14258,1515044193062,72 -14259,1515044383304,72 -14260,1515044682313,71 -14261,1515044966261,70 -14262,1515045146926,67 -14263,1515045326217,66 -14264,1515045564114,65 -14265,1515045656390,64 -14266,1515045845772,62 -14267,1515046022893,60 -14268,1515046107731,58 -14269,1515046261952,56 -14270,1515046352107,54 -14271,1515046680239,52 -14272,1515047061538,51 -14273,1515047142973,49 -14274,1515047164577,47 -14275,1515047223017,49 -14276,1515047243811,48 -14277,1515047278941,52 -14278,1515047331708,53 -14279,1515047372445,54 -14280,1515047409901,55 -14281,1515047482319,55 -14282,1515047651756,54 -14283,1515047719993,52 -14284,1515047731401,51 -14285,1515047767357,59 -14286,1515048201219,60 -14287,1515048205684,57 -14288,1515048449780,86 -14289,1515048681369,84 -14290,1515049075663,81 -14291,1515049336066,78 -14292,1515049417270,76 -14293,1515049461503,74 -14294,1515049601078,75 -14295,1515049686701,77 -14296,1515050013600,75 -14297,1515050452342,73 -14298,1515050463041,69 -14299,1515050506406,82 -14300,1515050681786,87 -14301,1515051607973,84 -14302,1515052462588,81 -14303,1515052572042,79 -14304,1515052732083,78 -14305,1515053180402,76 -14306,1515053207411,72 -14307,1515053242583,74 -14308,1515053397464,77 -14309,1515053738665,74 -14310,1515053993898,71 -14311,1515054104081,68 -14312,1515054213256,65 -14313,1515054352344,62 -14314,1515054450976,61 -14315,1515054609741,59 -14316,1515054614102,56 -14317,1515054668536,84 -14318,1515054765399,83 -14319,1515054769890,82 -14320,1515054963938,122 -14321,1515055309477,119 -14322,1515056442284,118 -14323,1515056881622,116 -14324,1515057400705,112 -14325,1515058101556,114 -14326,1515058350298,126 -14327,1515058406841,124 -14328,1515059077277,125 -14329,1515059236184,121 -14330,1515059292867,118 -14331,1515059600315,119 -14332,1515060031593,119 -14333,1515060082382,116 -14334,1515060165991,118 -14335,1515060222920,118 -14336,1515060274662,118 -14337,1515060376597,119 -14338,1515060432068,118 -14339,1515060847851,118 -14340,1515060921365,119 -14341,1515061262594,118 -14342,1515061520066,115 -14343,1515061691670,111 -14344,1515061895978,108 -14345,1515062073300,108 -14346,1515062397772,106 -14347,1515062515791,102 -14348,1515062529915,100 -14349,1515062663170,113 -14350,1515062850480,110 -14351,1515062969169,109 -14352,1515063013053,107 -14353,1515063118251,110 -14354,1515063358666,108 -14355,1515063745496,105 -14356,1515064156993,101 -14357,1515064488038,98 -14358,1515064605110,94 -14359,1515064753084,93 -14360,1515064809424,91 -14361,1515064940255,90 -14362,1515065095511,86 -14363,1515065208204,83 -14364,1515065323718,80 -14365,1515065652921,77 -14366,1515065894654,74 -14367,1515065980444,71 -14368,1515066099383,68 -14369,1515066166844,65 -14370,1515066476647,62 -14371,1515066758052,58 -14372,1515066924101,55 -14373,1515067033884,50 -14374,1515067143347,47 -14375,1515067361705,46 -14376,1515067543590,42 -14377,1515067580061,41 -14378,1515067646517,41 -14379,1515067736913,38 -14380,1515067793570,36 -14381,1515067906981,34 -14382,1515068125671,32 -14383,1515068183044,27 -14384,1515068273165,25 -14385,1515068314816,26 -14386,1515068336555,26 -14387,1515068381976,23 -14388,1515068402634,36 -14389,1515068457889,37 -14390,1515068525163,35 -14391,1515068586472,32 -14392,1515068657985,29 -14393,1515068693359,27 -14394,1515068751473,26 -14395,1515068851448,24 -14396,1515068943976,21 -14397,1515068948476,19 -14398,1515069000524,25 -14399,1515069004839,29 -14400,1515069035101,43 -14401,1515069068389,43 -14402,1515069111742,42 -14403,1515069159640,40 -14404,1515069353233,39 -14405,1515069576404,36 -14406,1515069596939,32 -14407,1515069607769,35 -14408,1515069672843,41 -14409,1515069700863,39 -14410,1515069952045,37 -14411,1515070246656,34 -14412,1515070419590,31 -14413,1515070540174,27 -14414,1515070607841,24 -14415,1515070722612,21 -14416,1515070739974,17 -14417,1515070855258,32 -14418,1515071003713,30 -14419,1515071037425,28 -14420,1515071051035,49 -14421,1515071192169,55 -14422,1515071484287,53 -14423,1515071520680,50 -14424,1515071834821,50 -14425,1515071876791,48 -14426,1515072004703,47 -14427,1515072153208,45 -14428,1515072258865,46 -14429,1515072286521,43 -14430,1515072470747,44 -14431,1515072487798,44 -14432,1515072529387,48 -14433,1515072572048,48 -14434,1515072745776,50 -14435,1515072977174,49 -14436,1515073048908,49 -14437,1515073143470,50 -14438,1515073247543,49 -14439,1515073391173,49 -14440,1515073438742,48 -14441,1515073627319,49 -14442,1515073713017,47 -14443,1515073876905,46 -14444,1515073934013,44 -14445,1515074022098,44 -14446,1515074087053,43 -14447,1515074170666,41 -14448,1515074413537,40 -14449,1515074536537,46 -14450,1515074733813,45 -14451,1515074840353,44 -14452,1515074974210,44 -14453,1515075001241,44 -14454,1515075091465,47 -14455,1515075217296,46 -14456,1515075305250,45 -14457,1515075376942,44 -14458,1515075394579,42 -14459,1515075615532,46 -14460,1515075763936,45 -14461,1515075924169,44 -14462,1515076054263,44 -14463,1515076278200,42 -14464,1515076351940,41 -14465,1515076460705,40 -14466,1515076494670,39 -14467,1515076561601,40 -14468,1515076629293,39 -14469,1515076975927,39 -14470,1515077000373,37 -14471,1515077140757,38 -14472,1515077260238,36 -14473,1515077335482,34 -14474,1515077453863,33 -14475,1515077458190,32 -14476,1515077483156,48 -14477,1515077677728,49 -14478,1515077864482,49 -14479,1515077979348,47 -14480,1515078033607,45 -14481,1515078441753,45 -14482,1515078869323,43 -14483,1515079187903,40 -14484,1515079448232,37 -14485,1515079482218,36 -14486,1515079602118,36 -14487,1515079784077,35 -14488,1515079788358,33 -14489,1515080033092,51 -14490,1515080370012,48 -14491,1515080483925,46 -14492,1515080500962,45 -14493,1515080519916,49 -14494,1515080602073,52 -14495,1515080781008,52 -14496,1515080802170,49 -14497,1515080875473,52 -14498,1515080912597,55 -14499,1515081013184,56 -14500,1515081145224,62 -14501,1515081396128,62 -14502,1515081837190,61 -14503,1515081874665,60 -14504,1515081936597,61 -14505,1515082191429,61 -14506,1515082454439,59 -14507,1515082574114,59 -14508,1515082831624,60 -14509,1515082888863,59 -14510,1515082967133,60 -14511,1515083071050,60 -14512,1515083207597,58 -14513,1515083324414,56 -14514,1515083447911,55 -14515,1515083507455,53 -14516,1515083633968,53 -14517,1515083667846,52 -14518,1515083756903,53 -14519,1515083860707,52 -14520,1515083949409,52 -14521,1515084089991,54 -14522,1515084149293,53 -14523,1515084228075,53 -14524,1515084331539,53 -14525,1515084491627,52 -14526,1515084631295,51 -14527,1515084643390,49 -14528,1515084732938,56 -14529,1515084838915,56 -14530,1515084993138,56 -14531,1515085171063,54 -14532,1515085238739,55 -14533,1515085294596,56 -14534,1515085361760,56 -14535,1515085516209,56 -14536,1515085563095,54 -14537,1515085719015,55 -14538,1515085876172,53 -14539,1515086127699,52 -14540,1515086244888,50 -14541,1515086298237,50 -14542,1515086426752,49 -14543,1515086444391,48 -14544,1515086657277,52 -14545,1515086885539,50 -14546,1515087071342,49 -14547,1515087140821,47 -14548,1515087223133,47 -14549,1515087445479,45 -14550,1515087677303,43 -14551,1515087754364,41 -14552,1515087878324,40 -14553,1515088018961,38 -14554,1515088037367,38 -14555,1515088089560,40 -14556,1515088262409,39 -14557,1515088289376,38 -14558,1515088345025,39 -14559,1515088399896,40 -14560,1515088453320,40 -14561,1515088616570,39 -14562,1515088781758,37 -14563,1515088835136,35 -14564,1515088941667,34 -14565,1515089130631,32 -14566,1515089184847,30 -14567,1515089189124,31 -14568,1515089319733,45 -14569,1515089448387,44 -14570,1515089619737,41 -14571,1515089636659,41 -14572,1515089719653,44 -14573,1515089854104,43 -14574,1515090098634,40 -14575,1515090206933,38 -14576,1515090361772,44 -14577,1515090652927,45 -14578,1515090967922,43 -14579,1515091004608,41 -14580,1515091065027,40 -14581,1515091095235,40 -14582,1515091133327,41 -14583,1515091161009,40 -14584,1515091564861,41 -14585,1515092130340,39 -14586,1515092361865,37 -14587,1515092472127,34 -14588,1515092551639,32 -14589,1515092581848,40 -14590,1515092753718,41 -14591,1515092824808,39 -14592,1515093139393,37 -14593,1515093185808,39 -14594,1515093299129,42 -14595,1515093464842,40 -14596,1515093478654,39 -14597,1515093486369,46 -14598,1515093543162,59 -14599,1515093648419,60 -14600,1515093659377,59 -14601,1515093723007,70 -14602,1515093882053,70 -14603,1515094117623,68 -14604,1515094328996,67 -14605,1515094409956,67 -14606,1515094553747,66 -14607,1515094792681,64 -14608,1515094947934,63 -14609,1515095153648,61 -14610,1515095157914,60 -14611,1515095185541,92 -14612,1515095284720,97 -14613,1515095288981,97 -14614,1515095551438,148 -14615,1515096240621,146 -14616,1515096861800,143 -14617,1515097000961,139 -14618,1515097405106,139 -14619,1515098263608,136 -14620,1515098930593,133 -14621,1515099162601,130 -14622,1515099397274,127 -14623,1515099796816,125 -14624,1515100293388,123 -14625,1515101349441,120 -14626,1515102372227,116 -14627,1515102959870,113 -14628,1515103039413,114 -14629,1515103470255,114 -14630,1515103615010,111 -14631,1515104133524,109 -14632,1515104260076,106 -14633,1515104413652,106 -14634,1515104506925,104 -14635,1515104702646,104 -14636,1515104806232,101 -14637,1515104959785,101 -14638,1515105081709,98 -14639,1515105266875,97 -14640,1515105277844,94 -14641,1515105335673,111 -14642,1515105398709,112 -14643,1515105461016,113 -14644,1515105511698,116 -14645,1515106354964,117 -14646,1515107214407,113 -14647,1515107496836,109 -14648,1515107730768,106 -14649,1515107917559,103 -14650,1515108260798,100 -14651,1515108395643,97 -14652,1515108477836,95 -14653,1515108606413,93 -14654,1515108641174,91 -14655,1515109190876,95 -14656,1515109278715,92 -14657,1515109493562,89 -14658,1515109905756,88 -14659,1515110452116,84 -14660,1515110780760,82 -14661,1515111003050,78 -14662,1515111248998,75 -14663,1515111291041,71 -14664,1515111388294,71 -14665,1515111432292,69 -14666,1515111606650,68 -14667,1515112040588,65 -14668,1515112327537,70 -14669,1515112419449,66 -14670,1515112575911,65 -14671,1515112772017,61 -14672,1515112825794,61 -14673,1515112882977,59 -14674,1515112908194,58 -14675,1515112943254,59 -14676,1515112962020,60 -14677,1515113514739,63 -14678,1515113878715,59 -14679,1515113902546,54 -14680,1515114063807,57 -14681,1515114352584,53 -14682,1515114403247,51 -14683,1515114624959,50 -14684,1515114845349,48 -14685,1515114912297,44 -14686,1515114972213,41 -14687,1515115318923,39 -14688,1515115681435,34 -14689,1515115730756,30 -14690,1515115754423,29 -14691,1515115802193,28 -14692,1515115843028,25 -14693,1515115891129,22 -14694,1515115935955,19 -14695,1515115991481,17 -14696,1515115995829,13 -14697,1515116063051,19 -14698,1515116125661,23 -14699,1515116143354,20 -14700,1515116287676,19 -14701,1515116301750,22 -14702,1515116319212,23 -14703,1515116350594,22 -14704,1515116361492,20 -14705,1515116393069,20 -14706,1515116442205,19 -14707,1515116480669,16 -14708,1515116501349,13 -14709,1515116523797,11 -14710,1515116565525,8 -14711,1515116616983,21 -14712,1515116631038,22 -14713,1515116641854,24 -14714,1515116702387,54 -14715,1515116779994,53 -14716,1515116870283,51 -14717,1515116874508,50 -14718,1515116911816,77 -14719,1515116998811,79 -14720,1515117525028,78 -14721,1515117535981,75 -14722,1515117645104,88 -14723,1515118067016,87 -14724,1515118194692,84 -14725,1515118769935,82 -14726,1515119229755,79 -14727,1515119619342,76 -14728,1515120156926,73 -14729,1515120431028,71 -14730,1515120597928,68 -14731,1515120787336,67 -14732,1515121118660,64 -14733,1515121466393,62 -14734,1515121529055,59 -14735,1515121563178,59 -14736,1515121779560,60 -14737,1515121974666,58 -14738,1515121999501,56 -14739,1515122090770,59 -14740,1515122534267,57 -14741,1515122935482,64 -14742,1515123002906,64 -14743,1515123131396,65 -14744,1515123449534,65 -14745,1515123585885,65 -14746,1515123885701,63 -14747,1515124062200,60 -14748,1515124106841,58 -14749,1515124183084,58 -14750,1515124245096,58 -14751,1515124296800,58 -14752,1515124345793,58 -14753,1515124368360,59 -14754,1515124555906,62 -14755,1515124856503,63 -14756,1515125013236,60 -14757,1515125061384,59 -14758,1515125120843,60 -14759,1515125207063,59 -14760,1515125352772,57 -14761,1515125565520,54 -14762,1515125784103,53 -14763,1515125940817,51 -14764,1515126123772,50 -14765,1515126263358,49 -14766,1515126500005,48 -14767,1515126778673,45 -14768,1515126980863,43 -14769,1515127081338,40 -14770,1515127146875,39 -14771,1515127181560,38 -14772,1515127243600,37 -14773,1515127309435,37 -14774,1515127365212,36 -14775,1515127571670,37 -14776,1515127813202,36 -14777,1515127901538,38 -14778,1515127933856,36 -14779,1515128110510,36 -14780,1515128276380,36 -14781,1515128336621,34 -14782,1515128405681,33 -14783,1515128515345,32 -14784,1515128627624,30 -14785,1515128706854,29 -14786,1515128831313,27 -14787,1515128954446,25 -14788,1515129016737,23 -14789,1515129121981,21 -14790,1515129220970,19 -14791,1515129292358,18 -14792,1515129376788,16 -14793,1515129411534,15 -14794,1515129469178,14 -14795,1515129564789,12 -14796,1515129622946,10 -14797,1515129654499,11 -14798,1515129669804,10 -14799,1515129691266,9 -14800,1515129812409,8 -14801,1515129982316,6 -14802,1515130044642,6 -14803,1515130063326,4 -14804,1515130092161,3 -14805,1515130113991,3 -14806,1515130122875,2 -14807,1515130138933,1 -14808,1515130148165,1 -14809,1515130163883,1 -14810,1515130176008,1 -14811,1515130184447,1 -14812,1515130193062,1 -14813,1515130205047,1 -14814,1515130213376,1 -14815,1515130222365,1 -14816,1515130231516,1 -14817,1515130241058,1 -14818,1515130249785,1 -14819,1515130259101,2 -14820,1515130271246,1 -14821,1515130283699,1 -14822,1515130295701,7 -14823,1515130311176,8 -14824,1515130330203,7 -14825,1515130351643,8 -14826,1515130394251,7 -14827,1515130426704,7 -14828,1515130458211,5 -14829,1515130490763,5 -14830,1515130502810,4 -14831,1515130526197,4 -14832,1515130548386,3 -14833,1515130567507,2 -14834,1515130580465,2 -14835,1515130599434,2 -14836,1515130621354,2 -14837,1515130650929,1 -14838,1515130670647,1 -14839,1515130678762,2 -14840,1515130691480,3 -14841,1515130703424,1 -14842,1515130712126,1 -14843,1515130724316,1 -14844,1515130732937,1 -14845,1515130741928,1 -14846,1515130750570,1 -14847,1515130763207,1 -14848,1515130772070,1 -14849,1515130781168,1 -14850,1515130790095,1 -14851,1515130798666,1 -14852,1515130807576,1 -14853,1515130819772,1 -14854,1515130831971,2 -14855,1515130844284,2 -14856,1515130856267,2 -14857,1515130871460,2 -14858,1515130883519,2 -14859,1515130898840,3 -14860,1515130911289,4 -14861,1515130930243,4 -14862,1515130945758,4 -14863,1515130965264,4 -14864,1515130980340,4 -14865,1515130996247,4 -14866,1515131008036,5 -14867,1515131023654,5 -14868,1515131059295,5 -14869,1515131091566,5 -14870,1515131106876,5 -14871,1515131120097,5 -14872,1515131134937,7 -14873,1515131144147,8 -14874,1515131169755,10 -14875,1515131199877,11 -14876,1515131219309,11 -14877,1515131235345,12 -14878,1515131252115,12 -14879,1515131268043,16 -14880,1515131389692,17 -14881,1515131544827,17 -14882,1515131758401,18 -14883,1515131934236,17 -14884,1515131942808,17 -14885,1515132011024,21 -14886,1515132124016,22 -14887,1515132265104,21 -14888,1515132450977,21 -14889,1515132816843,21 -14890,1515133069408,21 -14891,1515133092338,20 -14892,1515133117797,21 -14893,1515133146469,23 -14894,1515133165373,25 -14895,1515133180708,27 -14896,1515133268204,31 -14897,1515133364131,31 -14898,1515133459664,31 -14899,1515133544130,32 -14900,1515133633979,32 -14901,1515133759787,32 -14902,1515133811633,32 -14903,1515133830235,32 -14904,1515133929193,36 -14905,1515134069051,35 -14906,1515134125059,35 -14907,1515134184425,36 -14908,1515134239965,36 -14909,1515134342160,37 -14910,1515134411111,36 -14911,1515134488638,37 -14912,1515134593809,37 -14913,1515134733843,37 -14914,1515134863428,36 -14915,1515134917128,36 -14916,1515134959004,36 -14917,1515134984711,37 -14918,1515135116311,39 -14919,1515135256760,39 -14920,1515135328897,38 -14921,1515135390842,39 -14922,1515135506687,39 -14923,1515135688298,39 -14924,1515135832911,38 -14925,1515135938046,38 -14926,1515135976863,38 -14927,1515136002128,40 -14928,1515136060635,42 -14929,1515136124622,43 -14930,1515136156467,43 -14931,1515136350577,46 -14932,1515136452080,45 -14933,1515136600823,44 -14934,1515136756130,44 -14935,1515136934836,43 -14936,1515137406500,42 -14937,1515137792229,42 -14938,1515137824558,40 -14939,1515137853300,42 -14940,1515137914578,44 -14941,1515137998981,44 -14942,1515138070947,44 -14943,1515138214576,43 -14944,1515138359989,43 -14945,1515138484247,42 -14946,1515138563614,42 -14947,1515138614073,41 -14948,1515138870519,41 -14949,1515138980012,40 -14950,1515139014382,40 -14951,1515139088318,40 -14952,1515139171391,41 -14953,1515139188885,40 -14954,1515139250481,43 -14955,1515139395183,43 -14956,1515139594677,42 -14957,1515139671494,42 -14958,1515139798752,41 -14959,1515139844369,40 -14960,1515139848777,41 -14961,1515140009936,61 -14962,1515140200299,60 -14963,1515140221214,59 -14964,1515140270009,64 -14965,1515140323532,65 -14966,1515140409362,65 -14967,1515140466778,65 -14968,1515140605302,66 -14969,1515141151804,65 -14970,1515141618782,63 -14971,1515141670853,60 -14972,1515141735897,62 -14973,1515141875227,62 -14974,1515142074117,61 -14975,1515142447124,60 -14976,1515142517906,59 -14977,1515142551742,59 -14978,1515142623057,62 -14979,1515142705976,62 -14980,1515142877574,62 -14981,1515142905398,60 -14982,1515142922883,64 -14983,1515143188735,70 -14984,1515143446171,68 -14985,1515143583697,68 -14986,1515143780083,66 -14987,1515143857565,65 -14988,1515143930029,64 -14989,1515144040341,64 -14990,1515144283011,62 -14991,1515144561609,60 -14992,1515144592997,59 -14993,1515144684738,62 -14994,1515144818601,62 -14995,1515144863845,62 -14996,1515145078631,64 -14997,1515145426056,62 -14998,1515145437187,60 -14999,1515145481600,71 -15000,1515145628331,73 -15001,1515145658922,71 -15002,1515145733147,74 -15003,1515145819015,74 -15004,1515145846818,75 -15005,1515145904994,79 -15006,1515145955644,80 -15007,1515146009911,81 -15008,1515146206898,82 -15009,1515146469313,81 -15010,1515146795862,78 -15011,1515147072087,76 -15012,1515147490408,74 -15013,1515147604262,72 -15014,1515147960131,71 -15015,1515148509930,68 -15016,1515148567865,66 -15017,1515148690091,67 -15018,1515148737516,67 -15019,1515148768322,67 -15020,1515148895567,69 -15021,1515149028389,68 -15022,1515149376633,67 -15023,1515149547110,64 -15024,1515149762836,62 -15025,1515149965734,60 -15026,1515150381792,57 -15027,1515150396021,56 -15028,1515150414438,64 -15029,1515150466443,70 -15030,1515150500315,70 -15031,1515150558918,74 -15032,1515150587283,73 -15033,1515150887684,76 -15034,1515151002067,74 -15035,1515151059660,72 -15036,1515151174624,72 -15037,1515151182481,69 -15038,1515151201308,87 -15039,1515151351372,97 -15040,1515151534475,96 -15041,1515151698236,93 -15042,1515151925441,91 -15043,1515152211936,88 -15044,1515152242473,86 -15045,1515152572768,89 -15046,1515152927986,86 -15047,1515152942915,82 -15048,1515153084649,93 -15049,1515153196896,91 -15050,1515153291331,88 -15051,1515153610069,88 -15052,1515153782299,85 -15053,1515153916439,82 -15054,1515153920673,82 -15055,1515153925090,125 -15056,1515153950373,189 -15057,1515154311535,200 -15058,1515155336162,197 -15059,1515156052459,191 -15060,1515156278041,186 -15061,1515156322953,193 -15062,1515156645502,199 -15063,1515156978282,194 -15064,1515157149971,194 -15065,1515157222705,191 -15066,1515158123982,193 -15067,1515158323685,189 -15068,1515158383021,187 -15069,1515158878771,189 -15070,1515159082838,183 -15071,1515160101662,179 -15072,1515161004728,175 -15073,1515162038994,171 -15074,1515162208999,166 -15075,1515162848558,163 -15076,1515163643009,157 -15077,1515164042990,153 -15078,1515165240013,150 -15079,1515166489692,145 -15080,1515166785325,141 -15081,1515166806394,135 -15082,1515166943441,148 -15083,1515167290734,148 -15084,1515168206591,144 -15085,1515169213019,139 -15086,1515169295770,133 -15087,1515169419294,132 -15088,1515169444040,129 -15089,1515169551891,137 -15090,1515169741932,134 -15091,1515169990846,130 -15092,1515170094991,125 -15093,1515171249895,125 -15094,1515171555559,119 -15095,1515172023233,114 -15096,1515172196463,111 -15097,1515172297488,107 -15098,1515172442479,103 -15099,1515172594410,105 -15100,1515174410226,103 -15101,1515176381630,97 -15102,1515176402551,94 -15103,1515176614079,101 -15104,1515176621877,97 -15105,1515176828712,124 -15106,1515177113581,120 -15107,1515177164300,117 -15108,1515177226361,118 -15109,1515177347613,116 -15110,1515177480059,113 -15111,1515177894593,109 -15112,1515178349978,103 -15113,1515178373984,98 -15114,1515178385164,102 -15115,1515178483723,118 -15116,1515178922606,114 -15117,1515179058739,108 -15118,1515179305853,104 -15119,1515179694861,100 -15120,1515180504982,96 -15121,1515181018743,91 -15122,1515181170225,85 -15123,1515181188173,79 -15124,1515181310709,83 -15125,1515181496918,78 -15126,1515181529186,73 -15127,1515181597388,72 -15128,1515181683627,72 -15129,1515181715194,71 -15130,1515181719489,71 -15131,1515181852717,106 -15132,1515182026129,103 -15133,1515182094991,101 -15134,1515182340379,97 -15135,1515182463531,91 -15136,1515182481345,87 -15137,1515182579532,93 -15138,1515183107449,98 -15139,1515184006297,97 -15140,1515184673757,90 -15141,1515185143045,85 -15142,1515185795941,79 -15143,1515186120917,73 -15144,1515186369263,66 -15145,1515187056812,64 -15146,1515187656180,57 -15147,1515187670551,51 -15148,1515187674709,60 -15149,1515187736168,88 -15150,1515187897593,85 -15151,1515187935565,80 -15152,1515187986189,78 -15153,1515188281755,75 -15154,1515188609654,69 -15155,1515189117774,86 -15156,1515189809719,115 -15157,1515190590041,119 -15158,1515190597645,114 -15159,1515190972498,145 -15160,1515191390094,140 -15161,1515191541252,136 -15162,1515191773660,137 -15163,1515191840506,134 -15164,1515191901861,134 -15165,1515192496226,135 -15166,1515192530595,132 -15167,1515192614583,136 -15168,1515193340272,135 -15169,1515193700206,134 -15170,1515194102293,129 -15171,1515194343171,126 -15172,1515194569073,121 -15173,1515194836931,116 -15174,1515195086201,112 -15175,1515195421068,109 -15176,1515195447437,103 -15177,1515196242375,107 -15178,1515196495652,102 -15179,1515196877045,97 -15180,1515197061401,92 -15181,1515197128844,88 -15182,1515197299221,93 -15183,1515197523897,90 -15184,1515197548497,85 -15185,1515197726092,88 -15186,1515197747318,83 -15187,1515197778785,88 -15188,1515197891514,91 -15189,1515198274226,93 -15190,1515198588019,89 -15191,1515198701752,85 -15192,1515198723033,82 -15193,1515198827207,86 -15194,1515199322973,82 -15195,1515199447302,77 -15196,1515199580851,73 -15197,1515199687926,69 -15198,1515199775254,66 -15199,1515200237305,63 -15200,1515200352259,58 -15201,1515200360076,53 -15202,1515200578316,64 -15203,1515200615418,64 -15204,1515200742345,62 -15205,1515200856882,73 -15206,1515201039478,70 -15207,1515201508938,65 -15208,1515202067235,62 -15209,1515202310816,59 -15210,1515202604018,56 -15211,1515202774598,52 -15212,1515202829006,47 -15213,1515202853649,44 -15214,1515202950031,48 -15215,1515202954321,55 -15216,1515202985319,83 -15217,1515202996714,84 -15218,1515203295282,97 -15219,1515203340249,91 -15220,1515203385772,91 -15221,1515203431123,90 -15222,1515203452122,90 -15223,1515203500103,94 -15224,1515203609113,98 -15225,1515203765804,95 -15226,1515203838844,91 -15227,1515203967102,91 -15228,1515204015772,87 -15229,1515204216820,87 -15230,1515204308626,84 -15231,1515204649171,101 -15232,1515204929308,97 -15233,1515204979212,93 -15234,1515205888758,94 -15235,1515205955041,89 -15236,1515206147011,88 -15237,1515206154848,89 -15238,1515206349109,112 -15239,1515206616361,108 -15240,1515206939264,104 -15241,1515207849150,99 -15242,1515208041237,94 -15243,1515208406204,89 -15244,1515208941660,85 -15245,1515208989707,80 -15246,1515209155900,77 -15247,1515209216246,74 -15248,1515209238061,75 -15249,1515209273276,95 -15250,1515209308403,98 -15251,1515209509443,100 -15252,1515209595081,99 -15253,1515209657549,98 -15254,1515209777817,97 -15255,1515209815768,93 -15256,1515210041221,94 -15257,1515210072564,90 -15258,1515210109914,91 -15259,1515210124286,110 -15260,1515210434013,124 -15261,1515210445009,120 -15262,1515210548450,142 -15263,1515210623021,139 -15264,1515210701226,141 -15265,1515211117194,141 -15266,1515211717727,138 -15267,1515212121330,136 -15268,1515212257709,134 -15269,1515212580555,131 -15270,1515212598262,127 -15271,1515212883398,139 -15272,1515212946375,135 -15273,1515213384000,134 -15274,1515214011741,129 -15275,1515214155537,124 -15276,1515214362261,121 -15277,1515214658934,122 -15278,1515214670193,117 -15279,1515214809892,136 -15280,1515214844530,132 -15281,1515215029178,136 -15282,1515215144326,134 -15283,1515215239347,130 -15284,1515215912513,128 -15285,1515216697009,126 -15286,1515217332320,121 -15287,1515217502555,119 -15288,1515217554587,119 -15289,1515217680840,119 -15290,1515217946358,116 -15291,1515218306236,111 -15292,1515218330377,106 -15293,1515218460492,116 -15294,1515218888177,112 -15295,1515218940281,107 -15296,1515219008873,106 -15297,1515219098402,104 -15298,1515219325303,102 -15299,1515219386532,97 -15300,1515219452174,96 -15301,1515219730815,93 -15302,1515220093216,96 -15303,1515220241835,90 -15304,1515220418223,89 -15305,1515220564086,84 -15306,1515220878475,80 -15307,1515220932381,75 -15308,1515221084922,73 -15309,1515221340872,67 -15310,1515221361582,63 -15311,1515221468961,64 -15312,1515221480163,59 -15313,1515221484957,67 -15314,1515221500256,96 -15315,1515221624092,105 -15316,1515221982233,116 -15317,1515222321410,113 -15318,1515223398917,116 -15319,1515223469659,111 -15320,1515223591524,111 -15321,1515223629279,109 -15322,1515223849677,112 -15323,1515224085077,113 -15324,1515224106162,110 -15325,1515224188798,118 -15326,1515224492053,116 -15327,1515224533713,112 -15328,1515224809986,113 -15329,1515224850992,109 -15330,1515225065117,111 -15331,1515225451549,107 -15332,1515226007635,102 -15333,1515226171930,96 -15334,1515226295483,94 -15335,1515226464771,89 -15336,1515226558536,85 -15337,1515226576334,82 -15338,1515226891144,101 -15339,1515226976965,97 -15340,1515227366459,94 -15341,1515227890241,88 -15342,1515227921712,83 -15343,1515228078207,84 -15344,1515228129461,79 -15345,1515228180113,77 -15346,1515228211897,77 -15347,1515228610727,76 -15348,1515228615373,72 -15349,1515228670766,107 -15350,1515229173638,109 -15351,1515229424742,107 -15352,1515229663498,101 -15353,1515230480731,98 -15354,1515230501434,93 -15355,1515230518707,99 -15356,1515231285911,109 -15357,1515231580642,103 -15358,1515231610938,101 -15359,1515231655109,105 -15360,1515231763284,113 -15361,1515232132606,110 -15362,1515232293492,118 -15363,1515232300977,115 -15364,1515232429725,148 -15365,1515232537471,147 -15366,1515232641640,144 -15367,1515233136412,141 -15368,1515233300273,136 -15369,1515233442615,132 -15370,1515233499918,128 -15371,1515233799417,136 -15372,1515233817166,132 -15373,1515234070556,146 -15374,1515234519459,140 -15375,1515235027448,135 -15376,1515235216917,130 -15377,1515235379683,126 -15378,1515236271582,122 -15379,1515237098603,128 -15380,1515237424188,124 -15381,1515237484420,122 -15382,1515237539188,123 -15383,1515237547782,123 -15384,1515237635430,153 -15385,1515238388017,151 -15386,1515238751358,145 -15387,1515239128153,139 -15388,1515239481632,134 -15389,1515239520103,131 -15390,1515239654994,133 -15391,1515240395427,131 -15392,1515241330344,124 -15393,1515241337844,123 -15394,1515241528273,157 -15395,1515241632812,152 -15396,1515242341559,151 -15397,1515243292901,147 -15398,1515243992319,141 -15399,1515244699805,135 -15400,1515245371632,130 -15401,1515246037868,125 -15402,1515246393770,119 -15403,1515246421235,114 -15404,1515246479591,117 -15405,1515246537470,116 -15406,1515246728657,114 -15407,1515246858251,108 -15408,1515246934832,105 -15409,1515246953201,102 -15410,1515247419955,108 -15411,1515247979739,105 -15412,1515248000987,99 -15413,1515248360369,110 -15414,1515248932384,120 -15415,1515249023957,121 -15416,1515249234352,119 -15417,1515249739813,114 -15418,1515250310990,109 -15419,1515250816877,103 -15420,1515251387320,99 -15421,1515251473536,94 -15422,1515251497845,93 -15423,1515251552131,97 -15424,1515251582593,96 -15425,1515251908012,102 -15426,1515252008305,99 -15427,1515252066054,95 -15428,1515252073740,96 -15429,1515252242124,119 -15430,1515252694883,118 -15431,1515253200313,112 -15432,1515253408418,106 -15433,1515253516638,101 -15434,1515253619011,97 -15435,1515253785717,94 -15436,1515253905571,89 -15437,1515253909959,85 -15438,1515253964429,130 -15439,1515253991619,128 -15440,1515254275787,134 -15441,1515254283426,128 -15442,1515254318048,160 -15443,1515254938484,167 -15444,1515255434754,159 -15445,1515255562170,154 -15446,1515256072163,151 -15447,1515256495635,146 -15448,1515257037945,139 -15449,1515257242373,151 -15450,1515257358040,148 -15451,1515257796527,143 -15452,1515258941791,136 -15453,1515259232011,129 -15454,1515259296665,124 -15455,1515259464806,126 -15456,1515259686858,128 -15457,1515260058169,122 -15458,1515260529474,115 -15459,1515260557742,113 -15460,1515261056776,118 -15461,1515261488354,113 -15462,1515261636731,107 -15463,1515262375939,102 -15464,1515263267770,114 -15465,1515263380674,109 -15466,1515263698639,107 -15467,1515263766549,102 -15468,1515263837123,100 -15469,1515263967296,98 -15470,1515264332369,94 -15471,1515264336749,90 -15472,1515264348113,134 -15473,1515264507412,164 -15474,1515264707243,160 -15475,1515266019432,154 -15476,1515268137579,148 -15477,1515268452965,141 -15478,1515268539861,136 -15479,1515268752889,132 -15480,1515268808192,127 -15481,1515268903093,124 -15482,1515268960515,123 -15483,1515269564325,123 -15484,1515269796345,133 -15485,1515269834578,130 -15486,1515269920058,132 -15487,1515269947526,128 -15488,1515270204813,133 -15489,1515270345291,127 -15490,1515270623917,126 -15491,1515270788291,122 -15492,1515270827274,116 -15493,1515270999393,117 -15494,1515271125312,131 -15495,1515271354424,127 -15496,1515271358725,124 -15497,1515271766528,187 -15498,1515271880506,180 -15499,1515271952050,176 -15500,1515272905937,175 -15501,1515273283756,168 -15502,1515273748535,161 -15503,1515274194642,154 -15504,1515275486884,152 -15505,1515275631320,147 -15506,1515276010187,144 -15507,1515276175843,138 -15508,1515276376799,134 -15509,1515276980403,129 -15510,1515277184646,129 -15511,1515277633099,123 -15512,1515278226696,117 -15513,1515278438899,115 -15514,1515278678558,110 -15515,1515279205897,103 -15516,1515279411875,98 -15517,1515279933967,93 -15518,1515280145662,86 -15519,1515280173363,80 -15520,1515280200753,80 -15521,1515280404347,79 -15522,1515280443349,74 -15523,1515280475498,77 -15524,1515280526724,77 -15525,1515280773129,77 -15526,1515280807245,71 -15527,1515280878127,70 -15528,1515280977891,66 -15529,1515281090161,76 -15530,1515281180843,72 -15531,1515281218707,67 -15532,1515281400701,64 -15533,1515281582951,59 -15534,1515281812700,54 -15535,1515281846879,49 -15536,1515281948051,46 -15537,1515281976782,41 -15538,1515282232841,61 -15539,1515282453356,58 -15540,1515282515140,58 -15541,1515282602656,55 -15542,1515282627537,71 -15543,1515282668881,79 -15544,1515282792186,78 -15545,1515282976124,74 -15546,1515283227791,71 -15547,1515283280618,66 -15548,1515283379680,64 -15549,1515283542255,61 -15550,1515283701979,57 -15551,1515283896348,53 -15552,1515283935459,49 -15553,1515284053270,47 -15554,1515284090514,43 -15555,1515284129730,42 -15556,1515284337966,41 -15557,1515284404785,36 -15558,1515284462760,32 -15559,1515284480635,28 -15560,1515284545374,31 -15561,1515284719968,28 -15562,1515284734195,22 -15563,1515284763021,22 -15564,1515284784233,18 -15565,1515284798641,15 -15566,1515284817484,13 -15567,1515284832098,10 -15568,1515284840065,7 -15569,1515284865085,6 -15570,1515284872444,2 -15571,1515284880141,1 -15572,1515284888229,18 -15573,1515284903404,33 -15574,1515284941571,34 -15575,1515284970406,33 -15576,1515285032575,32 -15577,1515285063218,29 -15578,1515285258046,27 -15579,1515285272270,25 -15580,1515285290184,26 -15581,1515285314568,27 -15582,1515285415924,27 -15583,1515285443564,26 -15584,1515285493885,24 -15585,1515285522000,21 -15586,1515285526355,23 -15587,1515285578628,33 -15588,1515285641906,36 -15589,1515285704668,34 -15590,1515285799284,32 -15591,1515285850675,28 -15592,1515285892805,26 -15593,1515285901015,27 -15594,1515285943668,32 -15595,1515286021906,31 -15596,1515286097717,28 -15597,1515286134640,60 -15598,1515286263606,62 -15599,1515286396888,62 -15600,1515286686943,62 -15601,1515286900858,59 -15602,1515286962073,58 -15603,1515287029491,58 -15604,1515287128894,57 -15605,1515287163538,55 -15606,1515287171307,57 -15607,1515287307535,72 -15608,1515287799897,71 -15609,1515287814023,68 -15610,1515287882668,77 -15611,1515287974325,77 -15612,1515288421177,75 -15613,1515288569633,72 -15614,1515288601249,71 -15615,1515288619105,73 -15616,1515288819987,78 -15617,1515288850940,77 -15618,1515288951321,78 -15619,1515289138355,77 -15620,1515289163479,78 -15621,1515289215000,84 -15622,1515289363106,86 -15623,1515289480756,85 -15624,1515289524828,85 -15625,1515289627832,89 -15626,1515289755950,88 -15627,1515290345885,87 -15628,1515290727204,86 -15629,1515290745430,83 -15630,1515290878931,90 -15631,1515291176014,90 -15632,1515291361503,88 -15633,1515291396719,86 -15634,1515291527331,88 -15635,1515291586658,86 -15636,1515291751049,88 -15637,1515291762365,85 -15638,1515291939432,101 -15639,1515292283511,99 -15640,1515292294438,96 -15641,1515292437462,114 -15642,1515292597833,112 -15643,1515292605645,113 -15644,1515292738582,145 -15645,1515293512820,144 -15646,1515293636662,140 -15647,1515294686966,139 -15648,1515294853049,135 -15649,1515295170715,134 -15650,1515295245953,130 -15651,1515295496656,130 -15652,1515296622047,126 -15653,1515296776907,123 -15654,1515296798466,121 -15655,1515296891801,130 -15656,1515297173644,130 -15657,1515297600535,127 -15658,1515297760705,122 -15659,1515297834880,121 -15660,1515298047666,121 -15661,1515298096279,118 -15662,1515298107341,118 -15663,1515298235287,141 -15664,1515298313500,139 -15665,1515298465158,138 -15666,1515298836654,136 -15667,1515299062433,133 -15668,1515299126567,130 -15669,1515299204591,130 -15670,1515299300878,129 -15671,1515299440539,127 -15672,1515299906878,123 -15673,1515300162385,122 -15674,1515300592143,119 -15675,1515300973200,115 -15676,1515301235843,112 -15677,1515301807563,108 -15678,1515301851588,105 -15679,1515302045692,105 -15680,1515302164458,103 -15681,1515302747857,101 -15682,1515302752157,98 -15683,1515303686549,147 -15684,1515303713919,142 -15685,1515304091238,149 -15686,1515305074808,144 -15687,1515305160962,145 -15688,1515305377681,144 -15689,1515305714398,140 -15690,1515306150876,135 -15691,1515306849201,130 -15692,1515307089386,125 -15693,1515307259641,120 -15694,1515307435392,120 -15695,1515307880198,116 -15696,1515308156504,111 -15697,1515308404229,107 -15698,1515309267778,104 -15699,1515309354206,99 -15700,1515309710497,96 -15701,1515309726582,90 -15702,1515309920939,98 -15703,1515310852458,94 -15704,1515310959126,89 -15705,1515311191913,86 -15706,1515311298481,83 -15707,1515311510920,88 -15708,1515311932985,83 -15709,1515312175041,78 -15710,1515312186172,78 -15711,1515312277506,91 -15712,1515312285030,88 -15713,1515312523445,111 -15714,1515312920177,105 -15715,1515313395066,103 -15716,1515313531029,102 -15717,1515313650020,98 -15718,1515313882935,96 -15719,1515314037946,92 -15720,1515314182619,88 -15721,1515314236479,87 -15722,1515314462716,87 -15723,1515314498178,83 -15724,1515314603850,83 -15725,1515314694281,81 -15726,1515315029800,78 -15727,1515315433606,74 -15728,1515315605036,68 -15729,1515315701059,63 -15730,1515315732929,64 -15731,1515315759106,64 -15732,1515315849812,64 -15733,1515316088070,60 -15734,1515316363844,57 -15735,1515316434226,53 -15736,1515316469499,51 -15737,1515316504695,49 -15738,1515316593020,55 -15739,1515316696959,52 -15740,1515317008534,48 -15741,1515317356499,53 -15742,1515317454994,49 -15743,1515317552286,46 -15744,1515317606645,59 -15745,1515318051131,59 -15746,1515318098856,54 -15747,1515318146369,53 -15748,1515318207519,51 -15749,1515318296460,49 -15750,1515318468184,46 -15751,1515318623733,44 -15752,1515318657729,40 -15753,1515318665509,38 -15754,1515318682825,45 -15755,1515319120234,53 -15756,1515319300974,51 -15757,1515319485870,47 -15758,1515319554386,44 -15759,1515319592271,41 -15760,1515319613801,40 -15761,1515319631167,41 -15762,1515319741761,44 -15763,1515319802711,53 -15764,1515319833754,53 -15765,1515320142160,54 -15766,1515320168513,51 -15767,1515320310799,52 -15768,1515320351570,49 -15769,1515320375521,49 -15770,1515320403794,52 -15771,1515320421541,54 -15772,1515320582521,57 -15773,1515320616586,54 -15774,1515320716409,53 -15775,1515320746771,50 -15776,1515320968849,49 -15777,1515321058709,46 -15778,1515321283678,43 -15779,1515321346435,41 -15780,1515321354136,39 -15781,1515321537716,47 -15782,1515321699165,43 -15783,1515321878543,67 -15784,1515321912534,64 -15785,1515321933793,71 -15786,1515321977950,76 -15787,1515322048377,76 -15788,1515322105083,76 -15789,1515322334409,76 -15790,1515322660086,74 -15791,1515322819106,71 -15792,1515323052436,67 -15793,1515323228670,65 -15794,1515323445335,63 -15795,1515323540103,60 -15796,1515323581934,58 -15797,1515323680346,58 -15798,1515323759146,56 -15799,1515323848333,53 -15800,1515324053222,52 -15801,1515324212553,49 -15802,1515324216772,53 -15803,1515324248203,79 -15804,1515324759347,81 -15805,1515325089734,78 -15806,1515325107187,75 -15807,1515325151540,81 -15808,1515325163083,82 -15809,1515325207464,94 -15810,1515325597846,95 -15811,1515325602245,100 -15812,1515325626552,150 -15813,1515325707233,174 -15814,1515325811658,175 -15815,1515326053692,174 -15816,1515326601332,171 -15817,1515327635973,167 -15818,1515327656959,162 -15819,1515327714519,177 -15820,1515327866959,179 -15821,1515328027147,176 -15822,1515328391302,175 -15823,1515328923914,172 -15824,1515329710649,170 -15825,1515329933062,166 -15826,1515330248744,163 -15827,1515330427233,158 -15828,1515330574788,155 -15829,1515331270121,152 -15830,1515331274563,148 -15831,1515331338427,224 -15832,1515331451533,229 -15833,1515331739953,229 -15834,1515331871243,224 -15835,1515332025178,221 -15836,1515332904669,219 -15837,1515332988925,214 -15838,1515333145710,215 -15839,1515333518976,212 -15840,1515333834050,206 -15841,1515334501689,202 -15842,1515335339711,195 -15843,1515335546424,189 -15844,1515336058283,185 -15845,1515337585070,180 -15846,1515337596307,174 -15847,1515337947521,205 -15848,1515338327095,201 -15849,1515338788829,196 -15850,1515340466539,189 -15851,1515340659066,183 -15852,1515341188324,178 -15853,1515341697952,173 -15854,1515341842317,172 -15855,1515342177222,171 -15856,1515342184829,165 -15857,1515342236557,210 -15858,1515343028694,212 -15859,1515343555071,205 -15860,1515343972885,200 -15861,1515344484195,195 -15862,1515345941671,190 -15863,1515345973370,183 -15864,1515346159339,190 -15865,1515347278914,186 -15866,1515348451876,179 -15867,1515348904686,173 -15868,1515349086109,167 -15869,1515349243759,162 -15870,1515349261189,159 -15871,1515349382151,175 -15872,1515349651813,174 -15873,1515349923189,167 -15874,1515350932130,162 -15875,1515350969211,155 -15876,1515351368424,160 -15877,1515351400486,153 -15878,1515351463134,156 -15879,1515351480872,154 -15880,1515352101302,167 -15881,1515352798942,165 -15882,1515353264704,158 -15883,1515353737175,149 -15884,1515354032294,142 -15885,1515354937233,137 -15886,1515355874524,133 -15887,1515356324632,126 -15888,1515356355574,120 -15889,1515356386896,122 -15890,1515356625363,124 -15891,1515356837810,117 -15892,1515357188355,110 -15893,1515357326827,103 -15894,1515357485117,96 -15895,1515357748631,88 -15896,1515357777134,82 -15897,1515358017484,82 -15898,1515358201156,75 -15899,1515358238882,67 -15900,1515358473817,64 -15901,1515358660418,56 -15902,1515358711270,48 -15903,1515358797805,58 -15904,1515358911668,54 -15905,1515359035131,47 -15906,1515359103702,40 -15907,1515359191246,38 -15908,1515359225670,33 -15909,1515359305814,37 -15910,1515359341682,32 -15911,1515359385517,27 -15912,1515359449457,49 -15913,1515359538969,51 -15914,1515359598476,48 -15915,1515359800130,45 -15916,1515359807791,40 -15917,1515359923251,46 -15918,1515360041456,40 -15919,1515360353484,44 -15920,1515360403292,41 -15921,1515360450137,38 -15922,1515360454629,35 -15923,1515360543278,47 -15924,1515360569222,42 -15925,1515360634252,39 -15926,1515360731567,35 -15927,1515360838463,29 -15928,1515360966650,24 -15929,1515361015529,20 -15930,1515361036646,14 -15931,1515361041283,50 -15932,1515361102412,74 -15933,1515361190466,74 -15934,1515361542374,72 -15935,1515361680222,68 -15936,1515361715263,66 -15937,1515361769680,64 -15938,1515361801382,64 -15939,1515361917868,65 -15940,1515362231839,61 -15941,1515362243181,56 -15942,1515362292916,63 -15943,1515362434323,61 -15944,1515362495262,57 -15945,1515362530242,54 -15946,1515362698932,52 -15947,1515363076603,66 -15948,1515363094236,60 -15949,1515363098676,64 -15950,1515363260162,94 -15951,1515363343366,90 -15952,1515363363888,87 -15953,1515363529546,92 -15954,1515363574274,87 -15955,1515363648963,87 -15956,1515363673947,84 -15957,1515363815206,112 -15958,1515363902205,114 -15959,1515363962899,112 -15960,1515363980079,111 -15961,1515364122568,122 -15962,1515364177230,118 -15963,1515364212056,117 -15964,1515364617225,127 -15965,1515365432937,123 -15966,1515365633715,117 -15967,1515365801851,113 -15968,1515366284869,110 -15969,1515366650030,105 -15970,1515366756382,102 -15971,1515366797900,110 -15972,1515367024275,113 -15973,1515367224484,109 -15974,1515367506773,106 -15975,1515367826403,101 -15976,1515368162811,102 -15977,1515368536032,97 -15978,1515369064729,99 -15979,1515369256772,97 -15980,1515369477569,103 -15981,1515369611981,99 -15982,1515369673278,97 -15983,1515370176283,96 -15984,1515370293990,92 -15985,1515370459551,90 -15986,1515370666611,86 -15987,1515370819867,83 -15988,1515371124499,79 -15989,1515371162969,80 -15990,1515371268383,85 -15991,1515371431848,83 -15992,1515371591091,79 -15993,1515371705111,76 -15994,1515371994440,74 -15995,1515372223570,71 -15996,1515372396178,67 -15997,1515372662230,67 -15998,1515372696646,63 -15999,1515372760958,64 -16000,1515372782596,64 -16001,1515372803899,66 -16002,1515372932897,69 -16003,1515373072625,67 -16004,1515373153639,64 -16005,1515373292595,61 -16006,1515373522623,58 -16007,1515373944720,54 -16008,1515373993379,51 -16009,1515374031923,50 -16010,1515374207395,48 -16011,1515374518479,45 -16012,1515374738025,41 -16013,1515374742494,38 -16014,1515374756972,54 -16015,1515374774570,59 -16016,1515374785442,63 -16017,1515374853603,77 -16018,1515375344030,75 -16019,1515375381645,70 -16020,1515375393031,70 -16021,1515375432424,80 -16022,1515375601314,80 -16023,1515375662596,85 -16024,1515375946584,84 -16025,1515376014202,81 -16026,1515376075671,80 -16027,1515376405820,78 -16028,1515376437158,73 -16029,1515376582580,74 -16030,1515376826924,70 -16031,1515376955162,65 -16032,1515377029420,75 -16033,1515377037058,73 -16034,1515377121531,92 -16035,1515377132606,89 -16036,1515377380422,104 -16037,1515377809594,102 -16038,1515377898565,98 -16039,1515378154799,98 -16040,1515378239871,94 -16041,1515378373364,90 -16042,1515378663124,93 -16043,1515378723255,89 -16044,1515378961526,88 -16045,1515379369701,85 -16046,1515379594245,81 -16047,1515379769599,78 -16048,1515379790693,73 -16049,1515379964641,80 -16050,1515380019625,94 -16051,1515380037288,94 -16052,1515380172344,103 -16053,1515380396769,105 -16054,1515380711752,102 -16055,1515381117964,100 -16056,1515381160028,96 -16057,1515381507319,102 -16058,1515381602520,98 -16059,1515381702058,97 -16060,1515381922484,98 -16061,1515382189390,101 -16062,1515382245144,98 -16063,1515382955061,102 -16064,1515383146162,101 -16065,1515383415608,98 -16066,1515383563376,95 -16067,1515383613632,92 -16068,1515383852116,93 -16069,1515383913066,90 -16070,1515384309011,90 -16071,1515384978916,87 -16072,1515385113658,86 -16073,1515385141137,83 -16074,1515385344407,87 -16075,1515385360369,83 -16076,1515385667642,92 -16077,1515385723190,88 -16078,1515385839507,88 -16079,1515385847215,85 -16080,1515385935909,107 -16081,1515386842669,106 -16082,1515387030885,101 -16083,1515387088381,100 -16084,1515387298299,99 -16085,1515387458414,96 -16086,1515387559043,93 -16087,1515387587182,90 -16088,1515387637313,94 -16089,1515387644797,92 -16090,1515388150895,119 -16091,1515388169060,115 -16092,1515388529541,126 -16093,1515388609262,121 -16094,1515388732177,120 -16095,1515388759739,116 -16096,1515388804909,120 -16097,1515388925702,122 -16098,1515388976423,118 -16099,1515389179148,120 -16100,1515389797731,117 -16101,1515389955721,114 -16102,1515389959971,113 -16103,1515390050390,172 -16104,1515390071208,170 -16105,1515390286027,184 -16106,1515390676205,178 -16107,1515391162720,173 -16108,1515391357910,167 -16109,1515391683497,162 -16110,1515392170040,158 -16111,1515392341866,152 -16112,1515392423445,147 -16113,1515392664611,144 -16114,1515392672352,149 -16115,1515392716664,192 -16116,1515392934808,199 -16117,1515393000826,201 -16118,1515393362345,202 -16119,1515393652372,196 -16120,1515393787608,192 -16121,1515394535886,196 -16122,1515394813429,192 -16123,1515395117290,186 -16124,1515396185551,182 -16125,1515396250358,176 -16126,1515396686168,176 -16127,1515397587734,171 -16128,1515397645208,165 -16129,1515397744957,167 -16130,1515397822525,164 -16131,1515397946269,163 -16132,1515398367959,159 -16133,1515398448957,153 -16134,1515398519577,162 -16135,1515398533557,162 -16136,1515398554769,193 -16137,1515399101795,207 -16138,1515399216216,202 -16139,1515399287081,199 -16140,1515399506435,199 -16141,1515399941917,195 -16142,1515400615805,189 -16143,1515400869734,181 -16144,1515401329814,178 -16145,1515401577705,172 -16146,1515401728285,166 -16147,1515401831943,161 -16148,1515401886311,157 -16149,1515402377739,161 -16150,1515402443979,154 -16151,1515402692279,154 -16152,1515403077520,154 -16153,1515403214833,149 -16154,1515403573690,144 -16155,1515404220897,138 -16156,1515404311228,131 -16157,1515404871030,130 -16158,1515405111854,123 -16159,1515405278999,118 -16160,1515405307008,113 -16161,1515405362989,115 -16162,1515405398845,113 -16163,1515405437724,115 -16164,1515405679541,115 -16165,1515406093153,109 -16166,1515406322996,101 -16167,1515406467780,95 -16168,1515406678377,91 -16169,1515406811812,85 -16170,1515407042131,80 -16171,1515407113149,73 -16172,1515407386171,69 -16173,1515407423841,62 -16174,1515407468326,62 -16175,1515407630955,58 -16176,1515407854059,57 -16177,1515407871810,51 -16178,1515407969886,51 -16179,1515408043128,46 -16180,1515408149653,53 -16181,1515408569818,49 -16182,1515408676742,42 -16183,1515408727767,36 -16184,1515408771184,33 -16185,1515408808541,27 -16186,1515408819280,23 -16187,1515408884032,22 -16188,1515408931379,20 -16189,1515408952785,15 -16190,1515408963548,25 -16191,1515408974989,24 -16192,1515408982862,30 -16193,1515409051069,33 -16194,1515409108423,29 -16195,1515409166526,25 -16196,1515409197832,25 -16197,1515409311489,23 -16198,1515409350434,18 -16199,1515409406534,16 -16200,1515409457454,11 -16201,1515409488331,5 -16202,1515409499565,1 -16203,1515409507356,27 -16204,1515409598411,31 -16205,1515409785556,36 -16206,1515409810419,33 -16207,1515409814788,32 -16208,1515409823258,44 -16209,1515409884773,52 -16210,1515409985746,50 -16211,1515410054151,46 -16212,1515410089431,42 -16213,1515410103713,42 -16214,1515410210446,44 -16215,1515410299340,63 -16216,1515410327752,65 -16217,1515410476459,66 -16218,1515410555023,67 -16219,1515410626031,65 -16220,1515410726312,63 -16221,1515410734194,61 -16222,1515411000320,75 -16223,1515411416254,71 -16224,1515411450738,68 -16225,1515411688971,68 -16226,1515411993053,66 -16227,1515412307834,62 -16228,1515412346775,58 -16229,1515412384597,60 -16230,1515412640778,60 -16231,1515412731452,59 -16232,1515412735766,57 -16233,1515412817535,84 -16234,1515413140941,83 -16235,1515413175186,82 -16236,1515413371443,96 -16237,1515413500035,104 -16238,1515413735534,102 -16239,1515413817398,100 -16240,1515413848654,102 -16241,1515413978031,107 -16242,1515414376350,105 -16243,1515415036258,100 -16244,1515415289936,97 -16245,1515415321065,94 -16246,1515415546722,98 -16247,1515416033272,95 -16248,1515416130997,93 -16249,1515416408307,94 -16250,1515416854502,91 -16251,1515417218429,89 -16252,1515417637516,86 -16253,1515417917209,83 -16254,1515418130505,81 -16255,1515418234112,77 -16256,1515418309086,75 -16257,1515418363767,75 -16258,1515418431163,74 -16259,1515418439447,72 -16260,1515418858661,90 -16261,1515418932764,91 -16262,1515419027849,92 -16263,1515419062205,93 -16264,1515419135192,99 -16265,1515419307510,98 -16266,1515419374037,95 -16267,1515420012139,95 -16268,1515420049893,91 -16269,1515420309634,92 -16270,1515420324453,89 -16271,1515420684354,100 -16272,1515421066195,97 -16273,1515421322426,93 -16274,1515421448338,91 -16275,1515421459188,90 -16276,1515421493463,106 -16277,1515421888257,108 -16278,1515422057360,107 -16279,1515422118700,104 -16280,1515422254900,104 -16281,1515422940750,101 -16282,1515423110798,96 -16283,1515423162062,93 -16284,1515423251704,93 -16285,1515423522679,92 -16286,1515423550573,88 -16287,1515423596565,94 -16288,1515423753200,93 -16289,1515423960538,90 -16290,1515424489559,87 -16291,1515424534214,85 -16292,1515424622193,87 -16293,1515424646281,89 -16294,1515425052158,93 -16295,1515425210134,89 -16296,1515425733298,85 -16297,1515425941062,82 -16298,1515425948880,78 -16299,1515425980542,98 -16300,1515426042567,99 -16301,1515426129565,98 -16302,1515426360877,95 -16303,1515426409024,91 -16304,1515426450701,94 -16305,1515426697434,94 -16306,1515426773887,89 -16307,1515426812082,88 -16308,1515427124119,97 -16309,1515427148719,98 -16310,1515427186238,104 -16311,1515427231280,106 -16312,1515427323126,106 -16313,1515427331797,105 -16314,1515427719182,132 -16315,1515428191723,128 -16316,1515428202894,124 -16317,1515428508059,146 -16318,1515428515731,142 -16319,1515428758417,181 -16320,1515429434955,177 -16321,1515430970488,172 -16322,1515431018213,175 -16323,1515431294091,177 -16324,1515432388273,173 -16325,1515432668902,168 -16326,1515432846639,163 -16327,1515433158961,160 -16328,1515433193453,154 -16329,1515433208732,159 -16330,1515433283238,180 -16331,1515433682805,179 -16332,1515433743782,173 -16333,1515433845915,189 -16334,1515434055703,188 -16335,1515434387370,184 -16336,1515434680275,181 -16337,1515434889999,177 -16338,1515435002108,173 -16339,1515435752076,170 -16340,1515436059463,166 -16341,1515436111429,163 -16342,1515436427806,166 -16343,1515436889482,161 -16344,1515436893889,154 -16345,1515437560570,232 -16346,1515437662542,229 -16347,1515439682163,227 -16348,1515440381082,219 -16349,1515440771294,213 -16350,1515441222130,207 -16351,1515442823267,200 -16352,1515443260192,193 -16353,1515443349007,185 -16354,1515443733224,182 -16355,1515444299610,176 -16356,1515444641225,169 -16357,1515444941920,164 -16358,1515445528549,159 -16359,1515446061452,153 -16360,1515446278199,156 -16361,1515446530084,151 -16362,1515446723570,145 -16363,1515447104668,141 -16364,1515447543911,137 -16365,1515447971211,132 -16366,1515448175927,126 -16367,1515448898311,122 -16368,1515449578045,115 -16369,1515449595587,111 -16370,1515449810272,118 -16371,1515450217530,119 -16372,1515450427749,114 -16373,1515450492354,107 -16374,1515450844783,104 -16375,1515451271887,98 -16376,1515451536948,101 -16377,1515452344996,99 -16378,1515452352830,93 -16379,1515452891273,115 -16380,1515452899262,110 -16381,1515453000647,136 -16382,1515453481937,132 -16383,1515454143441,125 -16384,1515454301628,120 -16385,1515454608055,115 -16386,1515454642605,108 -16387,1515454859569,112 -16388,1515455131036,107 -16389,1515455176168,101 -16390,1515455200596,100 -16391,1515455252290,102 -16392,1515455480109,101 -16393,1515455571981,95 -16394,1515455698599,93 -16395,1515455739636,88 -16396,1515455929606,86 -16397,1515455947468,79 -16398,1515456170477,82 -16399,1515456249894,87 -16400,1515456350816,85 -16401,1515456359166,81 -16402,1515456377161,99 -16403,1515456718838,104 -16404,1515456859282,99 -16405,1515457054924,96 -16406,1515457066715,89 -16407,1515457164311,100 -16408,1515457209067,97 -16409,1515457290249,95 -16410,1515457294840,94 -16411,1515457342013,138 -16412,1515457369517,139 -16413,1515457650153,143 -16414,1515457933680,150 -16415,1515458296319,143 -16416,1515458468253,136 -16417,1515459377345,143 -16418,1515460664550,136 -16419,1515461300524,151 -16420,1515461407825,145 -16421,1515461436890,141 -16422,1515461773706,145 -16423,1515461807813,142 -16424,1515461905894,145 -16425,1515462057058,142 -16426,1515462271261,136 -16427,1515462905914,131 -16428,1515462913570,125 -16429,1515463013859,162 -16430,1515463164743,170 -16431,1515463322525,168 -16432,1515463713430,163 -16433,1515464510955,159 -16434,1515464697863,154 -16435,1515465224264,149 -16436,1515465488751,143 -16437,1515465888651,138 -16438,1515465892993,132 -16439,1515466296364,198 -16440,1515466587246,191 -16441,1515466845399,185 -16442,1515467699902,181 -16443,1515467896515,173 -16444,1515469190252,168 -16445,1515469364919,203 -16446,1515469422034,198 -16447,1515469641461,202 -16448,1515470097687,196 -16449,1515470418436,190 -16450,1515470445941,184 -16451,1515470780211,193 -16452,1515471475866,187 -16453,1515471673891,181 -16454,1515471880856,177 -16455,1515472127488,172 -16456,1515472375878,167 -16457,1515472383759,161 -16458,1515472432218,203 -16459,1515472877344,204 -16460,1515473323439,197 -16461,1515474315850,191 -16462,1515474731062,183 -16463,1515476956536,176 -16464,1515477523137,168 -16465,1515478130315,161 -16466,1515478286245,153 -16467,1515478425979,148 -16468,1515478588804,142 -16469,1515478898888,135 -16470,1515479180592,135 -16471,1515479211899,129 -16472,1515479317210,130 -16473,1515479496764,126 -16474,1515479852691,120 -16475,1515479917495,113 -16476,1515480059268,109 -16477,1515480157414,103 -16478,1515480204766,97 -16479,1515480308691,107 -16480,1515480777206,102 -16481,1515481363351,110 -16482,1515481442124,105 -16483,1515481508147,101 -16484,1515481562086,96 -16485,1515481613931,93 -16486,1515481765109,90 -16487,1515482100355,88 -16488,1515482595766,81 -16489,1515482854514,74 -16490,1515483157768,70 -16491,1515483255606,67 -16492,1515483910990,64 -16493,1515483955711,56 -16494,1515484032919,53 -16495,1515484043926,48 -16496,1515484078231,53 -16497,1515484208764,50 -16498,1515484297295,49 -16499,1515484469055,43 -16500,1515484523582,37 -16501,1515484551413,32 -16502,1515484555838,39 -16503,1515484600788,60 -16504,1515484605158,56 -16505,1515484640326,80 -16506,1515484802440,78 -16507,1515484961316,81 -16508,1515485174535,75 -16509,1515485514204,72 -16510,1515485679674,65 -16511,1515485831496,84 -16512,1515486087906,82 -16513,1515486247873,83 -16514,1515486392564,78 -16515,1515486503874,73 -16516,1515486968632,69 -16517,1515486986142,64 -16518,1515487079422,66 -16519,1515487251597,61 -16520,1515487282544,55 -16521,1515487508522,55 -16522,1515487652540,54 -16523,1515487660469,49 -16524,1515487704892,62 -16525,1515488141239,61 -16526,1515488865251,56 -16527,1515488963562,50 -16528,1515489031907,45 -16529,1515489145678,60 -16530,1515489433883,57 -16531,1515489487582,53 -16532,1515489894583,51 -16533,1515490335591,46 -16534,1515490357468,40 -16535,1515490417160,39 -16536,1515490624954,36 -16537,1515490667456,30 -16538,1515490723092,27 -16539,1515490744189,59 -16540,1515490926765,62 -16541,1515490991347,58 -16542,1515491207973,56 -16543,1515492067399,52 -16544,1515492895350,49 -16545,1515492989805,44 -16546,1515493274891,41 -16547,1515493669620,41 -16548,1515493788839,37 -16549,1515493810153,34 -16550,1515493851642,34 -16551,1515493954778,39 -16552,1515493983045,37 -16553,1515494007767,35 -16554,1515494050486,35 -16555,1515494071966,33 -16556,1515494096525,33 -16557,1515494129716,32 -16558,1515494199255,55 -16559,1515494210592,59 -16560,1515494334554,68 -16561,1515494338898,65 -16562,1515494353504,98 -16563,1515494455024,109 -16564,1515494604505,107 -16565,1515494723195,104 -16566,1515494768051,102 -16567,1515494809365,104 -16568,1515494903215,106 -16569,1515495014384,105 -16570,1515495513419,102 -16571,1515495590940,99 -16572,1515495694101,102 -16573,1515495821632,101 -16574,1515496018313,99 -16575,1515496604708,95 -16576,1515496689491,93 -16577,1515496710274,92 -16578,1515496799407,99 -16579,1515497072186,99 -16580,1515497190702,96 -16581,1515497418094,94 -16582,1515497518028,90 -16583,1515497708904,89 -16584,1515497719704,86 -16585,1515497743771,103 -16586,1515497864394,110 -16587,1515498955767,107 -16588,1515499001499,103 -16589,1515499133045,104 -16590,1515499370713,100 -16591,1515499752337,96 -16592,1515499954943,92 -16593,1515499982381,88 -16594,1515500203987,93 -16595,1515500260115,88 -16596,1515500343722,92 -16597,1515500404153,92 -16598,1515500747603,90 -16599,1515500936770,87 -16600,1515501143095,83 -16601,1515501197220,79 -16602,1515501348073,79 -16603,1515501480897,85 -16604,1515501550284,84 -16605,1515501571175,97 -16606,1515501676392,107 -16607,1515501958792,105 -16608,1515502154761,102 -16609,1515502206810,99 -16610,1515502288578,99 -16611,1515502503006,98 -16612,1515502720905,94 -16613,1515502931694,92 -16614,1515503230793,88 -16615,1515503412283,85 -16616,1515503432974,83 -16617,1515503481875,87 -16618,1515503608366,91 -16619,1515503762990,89 -16620,1515503938500,86 -16621,1515504075946,84 -16622,1515504114478,82 -16623,1515504156105,82 -16624,1515504208798,89 -16625,1515504728613,91 -16626,1515505346284,86 -16627,1515505481636,82 -16628,1515505591567,80 -16629,1515505700408,78 -16630,1515505851490,75 -16631,1515506006212,72 -16632,1515506163938,69 -16633,1515506599208,66 -16634,1515506653294,62 -16635,1515506683857,62 -16636,1515506854559,63 -16637,1515507603375,59 -16638,1515507630836,56 -16639,1515507652551,57 -16640,1515507765687,61 -16641,1515507827298,58 -16642,1515507968516,57 -16643,1515508200379,53 -16644,1515508308300,49 -16645,1515508354600,45 -16646,1515508419474,43 -16647,1515508476967,40 -16648,1515508594221,37 -16649,1515508621639,34 -16650,1515508633022,34 -16651,1515508656942,37 -16652,1515508674854,36 -16653,1515508719268,38 -16654,1515508787137,37 -16655,1515508864735,34 -16656,1515508869498,31 -16657,1515508965359,43 -16658,1515509045383,41 -16659,1515509076400,38 -16660,1515509105970,42 -16661,1515509161645,41 -16662,1515509193029,57 -16663,1515509207520,64 -16664,1515509281169,72 -16665,1515509385850,71 -16666,1515509554268,70 -16667,1515509578982,69 -16668,1515509627571,74 -16669,1515509655812,75 -16670,1515509722600,78 -16671,1515509823603,76 -16672,1515509918957,75 -16673,1515510211893,74 -16674,1515510518917,71 -16675,1515510705116,68 -16676,1515510762389,64 -16677,1515511176587,64 -16678,1515511267549,65 -16679,1515511472703,64 -16680,1515511709841,61 -16681,1515511840122,59 -16682,1515511864923,56 -16683,1515511902036,58 -16684,1515512110290,58 -16685,1515512165396,64 -16686,1515512267522,69 -16687,1515512378346,67 -16688,1515512492893,64 -16689,1515512511312,65 -16690,1515512779338,70 -16691,1515512807268,68 -16692,1515513023580,70 -16693,1515513135027,67 -16694,1515513277114,69 -16695,1515513287710,66 -16696,1515513292348,79 -16697,1515513333765,117 -16698,1515513775301,121 -16699,1515514104489,117 -16700,1515514182983,114 -16701,1515514523084,113 -16702,1515514895709,111 -16703,1515514936364,108 -16704,1515515051323,110 -16705,1515515487696,109 -16706,1515515597515,110 -16707,1515516069384,110 -16708,1515516263410,106 -16709,1515516407628,103 -16710,1515516418454,102 -16711,1515516863201,122 -16712,1515517603813,118 -16713,1515517718995,114 -16714,1515517910226,112 -16715,1515518018406,110 -16716,1515518060071,107 -16717,1515518087586,113 -16718,1515518248700,121 -16719,1515518489607,118 -16720,1515518497221,116 -16721,1515518505020,147 -16722,1515518600587,188 -16723,1515519296705,189 -16724,1515519446924,186 -16725,1515519675084,185 -16726,1515519728614,182 -16727,1515519949598,184 -16728,1515520354216,180 -16729,1515520406087,176 -16730,1515521169986,178 -16731,1515521894992,173 -16732,1515522193491,169 -16733,1515522295500,163 -16734,1515522299771,161 -16735,1515522771139,247 -16736,1515524749880,243 -16737,1515524974676,236 -16738,1515525036937,230 -16739,1515525823441,235 -16740,1515525858140,231 -16741,1515525882829,240 -16742,1515526175282,256 -16743,1515526379336,251 -16744,1515527134651,246 -16745,1515527242574,239 -16746,1515527303887,237 -16747,1515527937223,239 -16748,1515528877811,233 -16749,1515529492882,225 -16750,1515529587208,219 -16751,1515529881930,220 -16752,1515529959817,215 -16753,1515530636064,216 -16754,1515531778801,209 -16755,1515532218783,202 -16756,1515532229767,196 -16757,1515532607814,238 -16758,1515533904712,231 -16759,1515534391272,224 -16760,1515534446581,218 -16761,1515535056411,221 -16762,1515535357206,214 -16763,1515535576875,209 -16764,1515536142526,208 -16765,1515536311386,202 -16766,1515536554476,196 -16767,1515536569126,190 -16768,1515536937416,216 -16769,1515537096755,210 -16770,1515537220379,208 -16771,1515537635124,205 -16772,1515537759188,198 -16773,1515537886502,194 -16774,1515538045197,189 -16775,1515538168822,183 -16776,1515538180657,178 -16777,1515538324341,207 -16778,1515538865301,201 -16779,1515539598494,193 -16780,1515539619787,185 -16781,1515539927599,196 -16782,1515539981596,188 -16783,1515540002596,189 -16784,1515540120639,203 -16785,1515540647072,197 -16786,1515540730684,189 -16787,1515540928230,186 -16788,1515541795464,178 -16789,1515542103177,169 -16790,1515542218853,165 -16791,1515542414188,158 -16792,1515542719415,152 -16793,1515543142090,144 -16794,1515543416664,136 -16795,1515543759871,128 -16796,1515544990108,125 -16797,1515545872268,136 -16798,1515546392093,131 -16799,1515547417406,124 -16800,1515548665517,115 -16801,1515548919271,107 -16802,1515549337904,99 -16803,1515549388068,92 -16804,1515549471618,90 -16805,1515549486161,84 -16806,1515549522127,90 -16807,1515549640485,87 -16808,1515549973930,81 -16809,1515550508020,72 -16810,1515550725655,64 -16811,1515550744386,67 -16812,1515550821379,67 -16813,1515551428473,60 -16814,1515551526862,52 -16815,1515551870584,45 -16816,1515551884876,37 -16817,1515551943581,37 -16818,1515551996747,35 -16819,1515552011216,29 -16820,1515552039138,25 -16821,1515552043623,36 -16822,1515552065371,71 -16823,1515552109667,73 -16824,1515552140483,69 -16825,1515552351517,68 -16826,1515552382781,62 -16827,1515552451628,62 -16828,1515552636365,57 -16829,1515552714295,50 -16830,1515552728756,47 -16831,1515552754352,47 -16832,1515552841953,43 -16833,1515553078539,38 -16834,1515553195156,32 -16835,1515553387278,70 -16836,1515553493037,65 -16837,1515553714639,60 -16838,1515553953572,54 -16839,1515554222933,54 -16840,1515554394651,48 -16841,1515554405686,49 -16842,1515554461179,66 -16843,1515554485432,63 -16844,1515554883392,64 -16845,1515555356795,59 -16846,1515555408179,56 -16847,1515555442142,57 -16848,1515555550256,55 -16849,1515555630013,51 -16850,1515555697662,46 -16851,1515555715445,45 -16852,1515555739131,45 -16853,1515555793157,47 -16854,1515555807360,43 -16855,1515555848545,45 -16856,1515555856356,41 -16857,1515555980717,70 -16858,1515556074429,66 -16859,1515556311256,62 -16860,1515556505590,58 -16861,1515556733254,57 -16862,1515556774140,52 -16863,1515556944248,51 -16864,1515557008214,46 -16865,1515557061854,43 -16866,1515557090072,41 -16867,1515557125159,39 -16868,1515557129544,52 -16869,1515557419132,76 -16870,1515557449692,72 -16871,1515557457305,74 -16872,1515557461718,93 -16873,1515557477658,139 -16874,1515557727552,155 -16875,1515557761717,151 -16876,1515558274668,156 -16877,1515558388233,169 -16878,1515558475613,167 -16879,1515558870722,165 -16880,1515559512658,160 -16881,1515559722650,165 -16882,1515559763995,161 -16883,1515559910740,169 -16884,1515559928208,177 -16885,1515560206306,197 -16886,1515560392552,192 -16887,1515560722115,191 -16888,1515561124667,187 -16889,1515562560861,182 -16890,1515562714397,177 -16891,1515562784905,175 -16892,1515563145261,175 -16893,1515563221369,171 -16894,1515563377307,170 -16895,1515563840365,167 -16896,1515564122385,161 -16897,1515564447893,157 -16898,1515564621267,152 -16899,1515565398612,147 -16900,1515565699879,141 -16901,1515567083386,136 -16902,1515567282962,130 -16903,1515567472244,126 -16904,1515567593610,123 -16905,1515568208431,120 -16906,1515568276240,121 -16907,1515568468854,122 -16908,1515568538853,119 -16909,1515568569391,117 -16910,1515568921018,119 -16911,1515569090253,115 -16912,1515569095320,114 -16913,1515569308266,162 -16914,1515569316346,157 -16915,1515569820582,197 -16916,1515570010324,191 -16917,1515570061866,189 -16918,1515570122115,190 -16919,1515570189934,191 -16920,1515570820082,192 -16921,1515571492997,186 -16922,1515572380514,189 -16923,1515573573666,185 -16924,1515574293700,180 -16925,1515574905730,175 -16926,1515575286561,169 -16927,1515575444900,164 -16928,1515575865502,161 -16929,1515576274430,155 -16930,1515576847531,149 -16931,1515577562092,147 -16932,1515578355055,142 -16933,1515578549495,135 -16934,1515579073427,130 -16935,1515579662353,124 -16936,1515579863538,118 -16937,1515579907201,112 -16938,1515579924601,112 -16939,1515580074039,120 -16940,1515580268328,114 -16941,1515580606912,108 -16942,1515581209164,107 -16943,1515581523677,102 -16944,1515581628883,98 -16945,1515582168480,93 -16946,1515582214164,86 -16947,1515582249475,84 -16948,1515582348704,85 -16949,1515582568558,80 -16950,1515582579316,75 -16951,1515582729879,84 -16952,1515582891253,82 -16953,1515583035487,77 -16954,1515583094686,72 -16955,1515583099010,71 -16956,1515583167062,104 -16957,1515583499849,107 -16958,1515583666663,100 -16959,1515583704174,94 -16960,1515583831343,93 -16961,1515583848783,87 -16962,1515583991228,91 -16963,1515584091586,87 -16964,1515584316097,81 -16965,1515584320731,75 -16966,1515584362789,106 -16967,1515584778079,105 -16968,1515584825557,99 -16969,1515585119193,109 -16970,1515585245440,102 -16971,1515585536346,99 -16972,1515585540707,103 -16973,1515585551960,178 -16974,1515585775511,219 -16975,1515586239314,214 -16976,1515586543847,212 -16977,1515586971294,206 -16978,1515587106239,200 -16979,1515587187126,199 -16980,1515587438154,196 -16981,1515587442500,191 -16982,1515587535115,288 -16983,1515588389618,291 -16984,1515589144918,283 -16985,1515589911132,287 -16986,1515590042451,280 -16987,1515590824935,277 -16988,1515591482035,269 -16989,1515591578881,261 -16990,1515592461878,259 -16991,1515592602083,250 -16992,1515592822856,248 -16993,1515592886724,243 -16994,1515593117965,245 -16995,1515593159647,239 -16996,1515593603063,244 -16997,1515593683743,236 -16998,1515594549014,234 -16999,1515595082085,226 -17000,1515595129322,218 -17001,1515595497317,220 -17002,1515596345694,211 -17003,1515597647281,203 -17004,1515599248546,193 -17005,1515599774014,185 -17006,1515600181139,176 -17007,1515600771649,170 -17008,1515600782633,162 -17009,1515600797036,190 -17010,1515600831237,215 -17011,1515600947177,220 -17012,1515602012171,214 -17013,1515602153755,231 -17014,1515602734451,227 -17015,1515603277281,241 -17016,1515603372855,234 -17017,1515603450682,231 -17018,1515604072844,234 -17019,1515604341966,229 -17020,1515604563936,225 -17021,1515604860379,219 -17022,1515604957375,211 -17023,1515605104680,207 -17024,1515605474697,202 -17025,1515605597295,194 -17026,1515606102863,188 -17027,1515606178477,180 -17028,1515606464744,178 -17029,1515607557311,170 -17030,1515607732073,161 -17031,1515607844344,154 -17032,1515608258094,149 -17033,1515608348917,140 -17034,1515608704602,135 -17035,1515609107962,126 -17036,1515609604234,117 -17037,1515609735081,109 -17038,1515609770008,105 -17039,1515610653339,110 -17040,1515610728438,101 -17041,1515610946865,96 -17042,1515611044722,89 -17043,1515611135055,81 -17044,1515611259001,74 -17045,1515611416022,67 -17046,1515611699947,59 -17047,1515611812713,53 -17048,1515611917314,46 -17049,1515612065944,40 -17050,1515612174104,31 -17051,1515612251470,31 -17052,1515612288818,24 -17053,1515612293090,17 -17054,1515612297442,17 -17055,1515612305338,19 -17056,1515612330100,37 -17057,1515612348150,33 -17058,1515612396603,29 -17059,1515612410745,22 -17060,1515612418539,20 -17061,1515612477171,19 -17062,1515612539011,16 -17063,1515612594065,9 -17064,1515612608739,1 -17065,1515612613052,1 -17066,1515612620889,6 -17067,1515612629826,2 -17068,1515612634046,1 -17069,1515612638445,1 -17070,1515612642802,1 -17071,1515612647389,1 -17072,1515612654755,1 -17073,1515612659116,1 -17074,1515612663503,4 -17075,1515612674686,1 -17076,1515612678885,1 -17077,1515612686535,1 -17078,1515612694526,1 -17079,1515612702943,1 -17080,1515612710634,1 -17081,1515612714783,1 -17082,1515612719832,20 -17083,1515612801941,29 -17084,1515612862603,25 -17085,1515612899865,22 -17086,1515612907746,19 -17087,1515612964865,22 -17088,1515613030887,19 -17089,1515613076352,16 -17090,1515613080669,15 -17091,1515613085052,19 -17092,1515613102613,27 -17093,1515613114314,26 -17094,1515613128449,32 -17095,1515613166657,33 -17096,1515613421680,37 -17097,1515613589657,35 -17098,1515613627286,34 -17099,1515613648328,31 -17100,1515613731698,31 -17101,1515613772806,33 -17102,1515613783996,31 -17103,1515613829537,33 -17104,1515613893295,31 -17105,1515613901303,27 -17106,1515613956588,31 -17107,1515614038293,28 -17108,1515614134368,24 -17109,1515614396085,39 -17110,1515614477848,51 -17111,1515614524469,57 -17112,1515614640493,58 -17113,1515614794717,56 -17114,1515614885606,55 -17115,1515615280373,53 -17116,1515615503200,51 -17117,1515615618299,51 -17118,1515615682039,52 -17119,1515615725930,52 -17120,1515615808278,52 -17121,1515615920242,51 -17122,1515616230706,50 -17123,1515616265896,50 -17124,1515616270290,52 -17125,1515616284944,77 -17126,1515616528869,88 -17127,1515616635039,86 -17128,1515616708615,86 -17129,1515616757008,86 -17130,1515616844773,87 -17131,1515616984844,86 -17132,1515617216496,87 -17133,1515617324127,83 -17134,1515617603154,83 -17135,1515617903918,81 -17136,1515617932033,78 -17137,1515617968038,81 -17138,1515618079490,84 -17139,1515618496224,85 -17140,1515618783568,82 -17141,1515618820889,81 -17142,1515619278447,83 -17143,1515619373002,81 -17144,1515619393626,80 -17145,1515619441684,86 -17146,1515619670028,87 -17147,1515619739914,84 -17148,1515619763998,83 -17149,1515619812262,88 -17150,1515619991245,89 -17151,1515620189535,85 -17152,1515620210715,83 -17153,1515620296232,89 -17154,1515620525840,92 -17155,1515620876312,94 -17156,1515621244277,93 -17157,1515621286550,92 -17158,1515621394996,95 -17159,1515621399365,93 -17160,1515621457381,143 -17161,1515621514141,147 -17162,1515621634502,150 -17163,1515621844212,148 -17164,1515621872330,144 -17165,1515622306437,152 -17166,1515623102291,148 -17167,1515623405673,145 -17168,1515623965884,141 -17169,1515624292329,137 -17170,1515625261807,133 -17171,1515625421519,129 -17172,1515625683660,125 -17173,1515625842451,122 -17174,1515626011729,119 -17175,1515626130478,117 -17176,1515626242165,114 -17177,1515626369397,112 -17178,1515626657641,109 -17179,1515626713450,105 -17180,1515626731128,105 -17181,1515626762530,114 -17182,1515627168987,117 -17183,1515627648962,116 -17184,1515627750604,112 -17185,1515627876763,110 -17186,1515628111320,107 -17187,1515628235963,106 -17188,1515628625240,103 -17189,1515628851470,99 -17190,1515628869210,94 -17191,1515629185149,106 -17192,1515629189822,107 -17193,1515629293711,159 -17194,1515629605343,158 -17195,1515629753884,157 -17196,1515629992606,154 -17197,1515630537126,149 -17198,1515630941880,144 -17199,1515632531036,140 -17200,1515633714535,136 -17201,1515633856626,131 -17202,1515634037803,128 -17203,1515634599632,128 -17204,1515634650621,123 -17205,1515635414531,124 -17206,1515635722930,122 -17207,1515635917954,118 -17208,1515636550464,114 -17209,1515636611748,109 -17210,1515636928017,107 -17211,1515637758176,103 -17212,1515637891957,99 -17213,1515637975474,95 -17214,1515638312445,92 -17215,1515638441301,89 -17216,1515638699293,84 -17217,1515638891864,79 -17218,1515639132843,75 -17219,1515639144938,71 -17220,1515639365296,81 -17221,1515639488645,76 -17222,1515639564040,72 -17223,1515639642400,69 -17224,1515639667241,66 -17225,1515639698432,81 -17226,1515640017417,88 -17227,1515640157652,84 -17228,1515640176763,80 -17229,1515640417191,86 -17230,1515641430493,84 -17231,1515641478526,79 -17232,1515641522567,78 -17233,1515641679731,78 -17234,1515641767371,73 -17235,1515641869334,70 -17236,1515641951546,67 -17237,1515642222696,66 -17238,1515642782613,64 -17239,1515642786932,60 -17240,1515643134436,88 -17241,1515643543625,83 -17242,1515643585061,80 -17243,1515643694672,78 -17244,1515643732253,75 -17245,1515643773289,79 -17246,1515643865664,79 -17247,1515644109595,75 -17248,1515644352015,72 -17249,1515644724885,71 -17250,1515644891578,67 -17251,1515645081854,63 -17252,1515645163687,58 -17253,1515645236136,59 -17254,1515645364976,57 -17255,1515645664819,52 -17256,1515646124975,48 -17257,1515646148832,42 -17258,1515646251896,44 -17259,1515646361523,40 -17260,1515646382741,62 -17261,1515646424298,67 -17262,1515646572961,69 -17263,1515646587897,67 -17264,1515646766227,73 -17265,1515646797673,76 -17266,1515646839681,77 -17267,1515647009763,77 -17268,1515647133683,74 -17269,1515647647471,71 -17270,1515648173614,67 -17271,1515648425930,62 -17272,1515648433916,59 -17273,1515648580643,73 -17274,1515648859592,69 -17275,1515648897082,65 -17276,1515648955809,66 -17277,1515649164986,64 -17278,1515649193144,61 -17279,1515649267388,62 -17280,1515649418952,61 -17281,1515649516504,64 -17282,1515649923409,65 -17283,1515650331656,61 -17284,1515650661578,56 -17285,1515651276377,54 -17286,1515651540117,50 -17287,1515651933562,46 -17288,1515651994870,42 -17289,1515652079085,39 -17290,1515652130483,36 -17291,1515652165265,40 -17292,1515652253245,39 -17293,1515652326399,63 -17294,1515652425740,63 -17295,1515652560209,62 -17296,1515652632889,60 -17297,1515653019925,60 -17298,1515653024307,56 -17299,1515653052321,84 -17300,1515653073427,86 -17301,1515653257856,92 -17302,1515653588121,89 -17303,1515654033283,87 -17304,1515654769836,83 -17305,1515655470969,82 -17306,1515655826598,78 -17307,1515656223791,75 -17308,1515656461723,72 -17309,1515656568514,68 -17310,1515656653899,67 -17311,1515656744208,66 -17312,1515656968117,63 -17313,1515656989828,61 -17314,1515657065045,64 -17315,1515657375880,62 -17316,1515657665865,58 -17317,1515657767716,55 -17318,1515658053190,53 -17319,1515658348727,49 -17320,1515658388656,52 -17321,1515658438470,51 -17322,1515658465785,50 -17323,1515658490408,52 -17324,1515658528846,54 -17325,1515658710751,56 -17326,1515658832317,56 -17327,1515658994519,53 -17328,1515659026379,50 -17329,1515659118275,55 -17330,1515659350010,53 -17331,1515659644241,49 -17332,1515659665589,48 -17333,1515659703717,51 -17334,1515659848632,51 -17335,1515659866448,49 -17336,1515660008094,52 -17337,1515660015855,50 -17338,1515660076074,61 -17339,1515660154903,59 -17340,1515660486047,75 -17341,1515661031382,71 -17342,1515661075172,68 -17343,1515661482137,70 -17344,1515662074787,67 -17345,1515662096259,66 -17346,1515662154486,72 -17347,1515662249265,72 -17348,1515662483697,71 -17349,1515662532685,68 -17350,1515662590587,67 -17351,1515662742406,67 -17352,1515662887900,64 -17353,1515662915240,62 -17354,1515663041517,65 -17355,1515663457896,62 -17356,1515663462237,59 -17357,1515663649682,88 -17358,1515663916335,86 -17359,1515664053592,83 -17360,1515664178001,81 -17361,1515664297898,81 -17362,1515664544432,81 -17363,1515664582843,78 -17364,1515664590528,84 -17365,1515664907415,106 -17366,1515665224334,105 -17367,1515665239104,103 -17368,1515665454247,117 -17369,1515665657893,114 -17370,1515665770582,110 -17371,1515666422667,109 -17372,1515667228955,105 -17373,1515667754056,109 -17374,1515668578538,105 -17375,1515669230211,101 -17376,1515669323181,100 -17377,1515669533109,100 -17378,1515669860246,96 -17379,1515670376812,95 -17380,1515670724470,92 -17381,1515670769991,89 -17382,1515671009591,90 -17383,1515671169930,86 -17384,1515671282663,84 -17385,1515671593099,82 -17386,1515672009595,77 -17387,1515672484547,73 -17388,1515672502290,70 -17389,1515672592618,76 -17390,1515672691428,74 -17391,1515672808703,72 -17392,1515672868970,70 -17393,1515673054559,68 -17394,1515673290418,67 -17395,1515673387808,63 -17396,1515673572890,61 -17397,1515673782370,58 -17398,1515673952097,54 -17399,1515674241456,67 -17400,1515674269441,67 -17401,1515674281488,73 -17402,1515674318209,84 -17403,1515674381625,86 -17404,1515674447837,85 -17405,1515674982864,84 -17406,1515674994122,80 -17407,1515675057786,93 -17408,1515675105575,92 -17409,1515675120632,93 -17410,1515675413372,104 -17411,1515675886419,101 -17412,1515675890741,97 -17413,1515676041004,147 -17414,1515676121790,147 -17415,1515676307631,147 -17416,1515676661486,143 -17417,1515676933811,139 -17418,1515677225523,136 -17419,1515677379422,131 -17420,1515677699291,128 -17421,1515678019740,125 -17422,1515678132877,121 -17423,1515678193835,120 -17424,1515678286441,122 -17425,1515678418918,121 -17426,1515678511951,118 -17427,1515678820705,116 -17428,1515678882498,112 -17429,1515679155422,113 -17430,1515679163269,109 -17431,1515679245126,137 -17432,1515679457332,134 -17433,1515679802977,133 -17434,1515679890642,130 -17435,1515680209336,128 -17436,1515680364868,126 -17437,1515680439257,122 -17438,1515680527693,128 -17439,1515680596294,127 -17440,1515680614645,126 -17441,1515680757481,137 -17442,1515681336313,133 -17443,1515682445265,129 -17444,1515683326525,124 -17445,1515683409459,118 -17446,1515683415009,119 -17447,1515683477109,166 -17448,1515684028879,166 -17449,1515684641178,160 -17450,1515685422898,157 -17451,1515685587752,151 -17452,1515685813974,147 -17453,1515686089694,142 -17454,1515686111277,139 -17455,1515686613413,149 -17456,1515686836940,142 -17457,1515687160204,154 -17458,1515687264871,149 -17459,1515687620365,147 -17460,1515688135194,142 -17461,1515688382742,137 -17462,1515688599868,132 -17463,1515688959887,128 -17464,1515689415100,125 -17465,1515689767029,132 -17466,1515690118051,127 -17467,1515690829267,122 -17468,1515691288706,125 -17469,1515691412302,121 -17470,1515691687818,118 -17471,1515691759561,114 -17472,1515692008823,112 -17473,1515692229504,107 -17474,1515692489139,103 -17475,1515692506972,98 -17476,1515692639294,105 -17477,1515692843360,102 -17478,1515693186908,99 -17479,1515693259239,93 -17480,1515693266956,91 -17481,1515693339667,112 -17482,1515693404459,112 -17483,1515693639020,110 -17484,1515694083651,105 -17485,1515694149227,100 -17486,1515694244833,98 -17487,1515694318694,94 -17488,1515694490909,91 -17489,1515694552653,89 -17490,1515694653735,87 -17491,1515694737471,84 -17492,1515694830332,80 -17493,1515694997812,78 -17494,1515695032964,72 -17495,1515695117441,71 -17496,1515695422007,67 -17497,1515695470276,62 -17498,1515695586512,58 -17499,1515695767253,53 -17500,1515695813605,48 -17501,1515695934760,46 -17502,1515695993499,48 -17503,1515696144530,46 -17504,1515696268866,42 -17505,1515696462185,38 -17506,1515696561736,32 -17507,1515696659408,35 -17508,1515696684240,32 -17509,1515696708983,32 -17510,1515696876518,37 -17511,1515697161060,31 -17512,1515697248526,26 -17513,1515697252833,49 -17514,1515697257235,72 -17515,1515697589711,108 -17516,1515697631631,104 -17517,1515697774806,105 -17518,1515698038957,100 -17519,1515698396577,96 -17520,1515698624029,92 -17521,1515698817521,88 -17522,1515698842136,83 -17523,1515699097870,86 -17524,1515699173366,83 -17525,1515699389165,81 -17526,1515699931348,78 -17527,1515700425743,73 -17528,1515700596095,69 -17529,1515700630697,65 -17530,1515700741315,65 -17531,1515700896450,78 -17532,1515701210190,75 -17533,1515701383351,71 -17534,1515701560415,67 -17535,1515701643146,64 -17536,1515701804730,61 -17537,1515701989485,58 -17538,1515702130224,56 -17539,1515702197186,53 -17540,1515702218667,52 -17541,1515702263897,61 -17542,1515702449707,60 -17543,1515702750668,56 -17544,1515702775714,51 -17545,1515703065697,52 -17546,1515703445880,48 -17547,1515703453885,70 -17548,1515703522052,90 -17549,1515703584311,89 -17550,1515703930352,89 -17551,1515703961344,84 -17552,1515704190502,87 -17553,1515704329928,85 -17554,1515704522876,81 -17555,1515704616282,86 -17556,1515704745425,84 -17557,1515704971052,82 -17558,1515705301982,78 -17559,1515705733694,76 -17560,1515705768161,72 -17561,1515705803489,74 -17562,1515705911057,75 -17563,1515706016660,73 -17564,1515706651471,71 -17565,1515707326821,66 -17566,1515707393582,62 -17567,1515707401727,60 -17568,1515707474587,73 -17569,1515707546802,71 -17570,1515707785776,70 -17571,1515707868196,67 -17572,1515708094366,66 -17573,1515708109250,62 -17574,1515708362333,68 -17575,1515708765752,64 -17576,1515708780537,66 -17577,1515708866178,73 -17578,1515709012680,71 -17579,1515709171694,68 -17580,1515709443810,65 -17581,1515709641108,75 -17582,1515709852655,74 -17583,1515710170216,72 -17584,1515710530420,68 -17585,1515710938514,65 -17586,1515711069558,62 -17587,1515711346941,61 -17588,1515711519378,59 -17589,1515711596288,56 -17590,1515711652236,55 -17591,1515711720687,54 -17592,1515711895386,53 -17593,1515712138248,50 -17594,1515712225896,47 -17595,1515712329146,47 -17596,1515712457505,45 -17597,1515712653228,43 -17598,1515712851334,40 -17599,1515712910153,37 -17600,1515713034610,35 -17601,1515713192498,33 -17602,1515713302293,29 -17603,1515713413938,27 -17604,1515713421573,24 -17605,1515713443567,28 -17606,1515713465039,27 -17607,1515713512969,26 -17608,1515713524570,24 -17609,1515713619518,26 -17610,1515713719612,24 -17611,1515713787817,21 -17612,1515713858229,18 -17613,1515713914585,14 -17614,1515713977457,25 -17615,1515714025719,41 -17616,1515714132625,41 -17617,1515714357676,42 -17618,1515714548854,40 -17619,1515714577751,37 -17620,1515714754193,37 -17621,1515714944808,36 -17622,1515715191758,34 -17623,1515715260604,35 -17624,1515715357793,33 -17625,1515715444515,32 -17626,1515715459342,30 -17627,1515715488824,33 -17628,1515715578497,32 -17629,1515715689349,31 -17630,1515715792992,30 -17631,1515715797350,29 -17632,1515715811831,43 -17633,1515716005812,47 -17634,1515716189360,44 -17635,1515716327839,42 -17636,1515716346140,40 -17637,1515716364005,42 -17638,1515716439766,45 -17639,1515716528855,43 -17640,1515716593681,42 -17641,1515716784179,43 -17642,1515716795831,42 -17643,1515716827873,47 -17644,1515716994770,48 -17645,1515717559231,48 -17646,1515718088342,44 -17647,1515718221913,40 -17648,1515718257298,49 -17649,1515718529855,51 -17650,1515718625425,50 -17651,1515718728801,49 -17652,1515718759931,49 -17653,1515718781435,50 -17654,1515718789308,54 -17655,1515719131233,68 -17656,1515719169935,66 -17657,1515719225607,68 -17658,1515719367277,67 -17659,1515719466658,65 -17660,1515719543056,64 -17661,1515720416986,65 -17662,1515721299433,63 -17663,1515721311591,61 -17664,1515721353013,71 -17665,1515721641792,72 -17666,1515721792372,69 -17667,1515722460250,68 -17668,1515722971370,73 -17669,1515723280270,72 -17670,1515723645808,70 -17671,1515723719278,67 -17672,1515723765479,67 -17673,1515723773198,69 -17674,1515723808939,91 -17675,1515723837485,94 -17676,1515724235238,100 -17677,1515724327586,102 -17678,1515724471996,102 -17679,1515724664924,100 -17680,1515724719484,98 -17681,1515724812302,100 -17682,1515724940980,100 -17683,1515724959777,98 -17684,1515725050911,107 -17685,1515725402950,106 -17686,1515725761734,104 -17687,1515726037892,101 -17688,1515726087820,99 -17689,1515727018856,99 -17690,1515727103730,97 -17691,1515727467046,97 -17692,1515728030079,95 -17693,1515728963199,92 -17694,1515729941796,88 -17695,1515730426602,85 -17696,1515730842679,82 -17697,1515730854595,79 -17698,1515731139042,92 -17699,1515731395977,89 -17700,1515731465729,86 -17701,1515732530260,86 -17702,1515733700357,82 -17703,1515733890191,78 -17704,1515733994586,75 -17705,1515734025219,77 -17706,1515734087426,80 -17707,1515734186145,81 -17708,1515734301159,80 -17709,1515734464772,80 -17710,1515734537810,77 -17711,1515734679131,76 -17712,1515734794021,74 -17713,1515734934158,72 -17714,1515735066699,69 -17715,1515735077554,67 -17716,1515735130606,79 -17717,1515735465687,79 -17718,1515735848640,75 -17719,1515735924963,71 -17720,1515736269691,71 -17721,1515736627978,68 -17722,1515736688787,64 -17723,1515736778028,62 -17724,1515737175252,60 -17725,1515737186549,56 -17726,1515737384231,65 -17727,1515737671083,63 -17728,1515737675837,61 -17729,1515737728544,88 -17730,1515738092655,88 -17731,1515738310848,83 -17732,1515738647388,88 -17733,1515738927002,87 -17734,1515739513780,84 -17735,1515739964649,80 -17736,1515740219982,76 -17737,1515740359826,75 -17738,1515740520706,75 -17739,1515740528395,72 -17740,1515740550573,91 -17741,1515740595262,96 -17742,1515741062079,97 -17743,1515741558330,97 -17744,1515741646840,95 -17745,1515741845146,93 -17746,1515742125586,90 -17747,1515742355036,85 -17748,1515742417920,81 -17749,1515742585746,81 -17750,1515742775236,78 -17751,1515743281372,75 -17752,1515743383197,71 -17753,1515743418888,70 -17754,1515743721909,72 -17755,1515744062644,77 -17756,1515744161366,73 -17757,1515744193864,72 -17758,1515744211958,74 -17759,1515744501218,81 -17760,1515744791825,78 -17761,1515744962668,74 -17762,1515744997119,71 -17763,1515745538193,71 -17764,1515745657431,73 -17765,1515745811255,72 -17766,1515745845863,69 -17767,1515745896855,70 -17768,1515746178245,69 -17769,1515746192378,65 -17770,1515746243480,72 -17771,1515746337569,70 -17772,1515746469057,68 -17773,1515746615971,67 -17774,1515746716397,74 -17775,1515746847872,75 -17776,1515747167759,76 -17777,1515747192017,72 -17778,1515747272142,77 -17779,1515747393046,75 -17780,1515747468021,73 -17781,1515747499258,73 -17782,1515747534748,76 -17783,1515747539172,78 -17784,1515747600898,122 -17785,1515747645524,123 -17786,1515747722290,126 -17787,1515748102777,125 -17788,1515748452849,121 -17789,1515748895585,118 -17790,1515749235143,115 -17791,1515749290151,112 -17792,1515749441935,112 -17793,1515749545478,109 -17794,1515749706627,107 -17795,1515749773651,103 -17796,1515749857738,101 -17797,1515750417834,99 -17798,1515751075019,103 -17799,1515751600739,99 -17800,1515751625210,95 -17801,1515752004702,101 -17802,1515752036165,96 -17803,1515752209941,99 -17804,1515752527262,96 -17805,1515752652660,91 -17806,1515752786729,91 -17807,1515752974269,90 -17808,1515753035664,87 -17809,1515753106853,86 -17810,1515753226726,84 -17811,1515753352671,82 -17812,1515753481228,79 -17813,1515753541868,76 -17814,1515753666244,75 -17815,1515753930769,72 -17816,1515754232381,75 -17817,1515754323285,73 -17818,1515754600609,70 -17819,1515754608556,66 -17820,1515754704087,82 -17821,1515754968223,79 -17822,1515755174748,75 -17823,1515755244722,72 -17824,1515755764083,70 -17825,1515755835589,65 -17826,1515756282091,69 -17827,1515756885272,64 -17828,1515757209457,59 -17829,1515757472670,71 -17830,1515757631135,69 -17831,1515757681804,66 -17832,1515757686121,65 -17833,1515757748365,97 -17834,1515758212964,97 -17835,1515758224208,92 -17836,1515758331555,106 -17837,1515759117453,104 -17838,1515760100296,100 -17839,1515760445598,95 -17840,1515760631180,101 -17841,1515760918740,102 -17842,1515761128433,101 -17843,1515761326063,98 -17844,1515761453687,94 -17845,1515761772639,93 -17846,1515762053173,89 -17847,1515762308615,85 -17848,1515762749091,81 -17849,1515762868213,79 -17850,1515763033898,76 -17851,1515763051798,73 -17852,1515763071251,77 -17853,1515763333692,83 -17854,1515763668760,80 -17855,1515763777162,77 -17856,1515763781562,74 -17857,1515764138233,110 -17858,1515764297728,107 -17859,1515764668692,108 -17860,1515764826297,104 -17861,1515764860385,100 -17862,1515764951432,103 -17863,1515765037424,102 -17864,1515765195602,99 -17865,1515765331988,96 -17866,1515765407232,93 -17867,1515765474970,93 -17868,1515765750483,92 -17869,1515766114582,88 -17870,1515766169472,88 -17871,1515767069762,88 -17872,1515768388035,85 -17873,1515768416017,80 -17874,1515768487876,82 -17875,1515768949610,80 -17876,1515769555685,76 -17877,1515769770432,71 -17878,1515769883069,70 -17879,1515769931010,67 -17880,1515770198478,65 -17881,1515770481702,62 -17882,1515770577521,60 -17883,1515770642746,59 -17884,1515770726844,78 -17885,1515770875705,78 -17886,1515771118895,77 -17887,1515771223425,76 -17888,1515771354161,74 -17889,1515771420744,72 -17890,1515771618352,70 -17891,1515771813733,66 -17892,1515771882528,65 -17893,1515771982204,63 -17894,1515772267977,62 -17895,1515772835732,59 -17896,1515772840579,57 -17897,1515773025747,82 -17898,1515773265054,79 -17899,1515773539350,75 -17900,1515773801128,71 -17901,1515774214699,71 -17902,1515775090374,68 -17903,1515775226710,67 -17904,1515775375984,65 -17905,1515775680682,61 -17906,1515775714930,58 -17907,1515775770946,58 -17908,1515775910704,57 -17909,1515775952269,55 -17910,1515776000733,55 -17911,1515776086169,55 -17912,1515776174269,52 -17913,1515776186736,50 -17914,1515776390498,56 -17915,1515776565084,53 -17916,1515776783729,50 -17917,1515777038971,45 -17918,1515777270157,42 -17919,1515777318828,38 -17920,1515777354101,46 -17921,1515777373884,46 -17922,1515777469536,48 -17923,1515777742453,45 -17924,1515778057811,42 -17925,1515778253298,38 -17926,1515778507351,35 -17927,1515778658310,32 -17928,1515778780487,27 -17929,1515778801591,24 -17930,1515778870577,23 -17931,1515778929605,20 -17932,1515778933956,18 -17933,1515778980234,42 -17934,1515779071910,42 -17935,1515779150517,39 -17936,1515779210716,47 -17937,1515779233363,46 -17938,1515779447355,48 -17939,1515779685873,44 -17940,1515779806864,41 -17941,1515779824697,39 -17942,1515780013242,41 -17943,1515780227911,38 -17944,1515780279088,35 -17945,1515780287686,34 -17946,1515780297065,40 -17947,1515780459657,47 -17948,1515780640618,44 -17949,1515780978023,40 -17950,1515781070015,38 -17951,1515781108042,36 -17952,1515781234677,39 -17953,1515781398074,40 -17954,1515781538879,37 -17955,1515781681326,35 -17956,1515781764363,32 -17957,1515781789158,50 -17958,1515781856228,52 -17959,1515781995998,52 -17960,1515782017319,50 -17961,1515782120943,52 -17962,1515782262926,55 -17963,1515782455740,54 -17964,1515782640208,53 -17965,1515782722230,51 -17966,1515782841323,50 -17967,1515782977293,49 -17968,1515783166559,49 -17969,1515783281004,47 -17970,1515783359848,45 -17971,1515783398600,46 -17972,1515783431294,45 -17973,1515783812124,45 -17974,1515783922501,46 -17975,1515784065341,46 -17976,1515784128989,44 -17977,1515784344367,43 -17978,1515784638393,40 -17979,1515784806172,39 -17980,1515784884936,37 -17981,1515784988031,36 -17982,1515785083172,34 -17983,1515785198339,33 -17984,1515785613632,32 -17985,1515785913821,30 -17986,1515785948519,28 -17987,1515786078250,27 -17988,1515786252424,26 -17989,1515786267527,24 -17990,1515786290077,27 -17991,1515786359669,27 -17992,1515786421721,25 -17993,1515786539761,24 -17994,1515786585415,23 -17995,1515786707713,21 -17996,1515786825326,19 -17997,1515786854196,31 -17998,1515787092013,31 -17999,1515787308759,30 -18000,1515787424232,28 -18001,1515787446651,27 -18002,1515787468938,26 -18003,1515787491136,27 -18004,1515787500761,28 -18005,1515787552328,33 -18006,1515787616271,32 -18007,1515787649391,32 -18008,1515787795480,33 -18009,1515787864071,32 -18010,1515787940994,32 -18011,1515788044452,31 -18012,1515788181416,31 -18013,1515788288613,29 -18014,1515788421953,32 -18015,1515788533981,31 -18016,1515788617445,29 -18017,1515788666556,28 -18018,1515788709349,27 -18019,1515788779332,26 -18020,1515788875920,26 -18021,1515788955305,25 -18022,1515789040043,27 -18023,1515789082390,26 -18024,1515789241645,25 -18025,1515789388712,23 -18026,1515789431113,21 -18027,1515789450447,20 -18028,1515789483074,21 -18029,1515789508918,20 -18030,1515789531022,21 -18031,1515789582890,22 -18032,1515789621490,20 -18033,1515789661004,24 -18034,1515789750429,25 -18035,1515789847170,23 -18036,1515790049507,22 -18037,1515790284965,22 -18038,1515790344139,22 -18039,1515790382993,21 -18040,1515790478539,20 -18041,1515790578006,19 -18042,1515790628321,20 -18043,1515790645066,19 -18044,1515790656936,20 -18045,1515790786511,23 -18046,1515790870042,26 -18047,1515790900017,29 -18048,1515790983827,31 -18049,1515791117016,30 -18050,1515791256719,29 -18051,1515791342767,28 -18052,1515791388234,27 -18053,1515791465571,28 -18054,1515791543432,27 -18055,1515791598887,26 -18056,1515791698866,25 -18057,1515791798161,25 -18058,1515791931086,26 -18059,1515792049361,26 -18060,1515792132762,25 -18061,1515792185365,26 -18062,1515792238870,26 -18063,1515792319556,26 -18064,1515792491929,25 -18065,1515792650740,25 -18066,1515792692933,24 -18067,1515792745517,24 -18068,1515792802445,24 -18069,1515792828999,23 -18070,1515792848617,24 -18071,1515792873935,26 -18072,1515792886201,28 -18073,1515793159249,33 -18074,1515793383546,32 -18075,1515793439471,31 -18076,1515793485061,31 -18077,1515793571695,32 -18078,1515793731977,31 -18079,1515793821066,29 -18080,1515793934376,29 -18081,1515793981674,28 -18082,1515794032058,28 -18083,1515794074454,29 -18084,1515794113405,28 -18085,1515794194796,28 -18086,1515794263887,28 -18087,1515794299537,28 -18088,1515794428863,27 -18089,1515794552693,26 -18090,1515794683858,26 -18091,1515794821034,27 -18092,1515794868564,27 -18093,1515794893839,26 -18094,1515794964364,27 -18095,1515795086175,27 -18096,1515795236806,25 -18097,1515795334042,24 -18098,1515795373251,25 -18099,1515795492711,24 -18100,1515795618081,23 -18101,1515795794160,22 -18102,1515795998544,22 -18103,1515796110550,22 -18104,1515796265788,23 -18105,1515796418944,25 -18106,1515796556183,23 -18107,1515796713384,23 -18108,1515796809879,24 -18109,1515796906059,22 -18110,1515796982335,22 -18111,1515797035323,21 -18112,1515797084798,22 -18113,1515797107545,21 -18114,1515797149872,22 -18115,1515797246960,22 -18116,1515797365534,22 -18117,1515797426444,21 -18118,1515797471487,20 -18119,1515797518517,21 -18120,1515797568471,21 -18121,1515797673517,21 -18122,1515797837257,20 -18123,1515797986204,19 -18124,1515798113556,18 -18125,1515798192884,18 -18126,1515798301024,17 -18127,1515798399987,16 -18128,1515798449413,16 -18129,1515798488564,16 -18130,1515798521029,17 -18131,1515798627468,17 -18132,1515798789454,17 -18133,1515798868769,16 -18134,1515798904581,16 -18135,1515799015885,16 -18136,1515799112725,16 -18137,1515799128922,15 -18138,1515799184765,16 -18139,1515799285736,15 -18140,1515799439389,14 -18141,1515799521005,14 -18142,1515799546886,13 -18143,1515799566023,13 -18144,1515799622273,15 -18145,1515799712573,16 -18146,1515799782351,15 -18147,1515799818250,15 -18148,1515799850226,16 -18149,1515799961116,16 -18150,1515800078873,15 -18151,1515800117866,15 -18152,1515800171546,14 -18153,1515800221410,14 -18154,1515800244861,14 -18155,1515800296899,14 -18156,1515800351244,14 -18157,1515800384308,14 -18158,1515800450634,14 -18159,1515800499858,14 -18160,1515800575289,13 -18161,1515800659248,12 -18162,1515800725185,12 -18163,1515800823076,11 -18164,1515800869500,11 -18165,1515801006234,11 -18166,1515801122109,10 -18167,1515801146975,9 -18168,1515801173083,9 -18169,1515801215780,10 -18170,1515801306887,9 -18171,1515801393648,10 -18172,1515801426226,10 -18173,1515801478729,13 -18174,1515801494593,13 -18175,1515801526817,13 -18176,1515801590720,14 -18177,1515801673139,15 -18178,1515801729273,14 -18179,1515801779375,13 -18180,1515801829771,14 -18181,1515801848748,13 -18182,1515801893968,15 -18183,1515801938622,15 -18184,1515802005231,16 -18185,1515802067366,16 -18186,1515802114815,16 -18187,1515802182106,16 -18188,1515802239448,17 -18189,1515802305516,17 -18190,1515802357769,16 -18191,1515802389468,16 -18192,1515802424934,16 -18193,1515802447310,18 -18194,1515802489575,19 -18195,1515802587691,20 -18196,1515802650870,20 -18197,1515802735836,19 -18198,1515802792747,19 -18199,1515802846380,20 -18200,1515802865656,19 -18201,1515802901347,21 -18202,1515802956814,21 -18203,1515803042568,22 -18204,1515803125589,21 -18205,1515803204968,21 -18206,1515803263503,21 -18207,1515803339353,21 -18208,1515803424112,20 -18209,1515803509443,20 -18210,1515803595814,20 -18211,1515803698180,20 -18212,1515803790635,19 -18213,1515803883611,19 -18214,1515804045084,20 -18215,1515804160036,19 -18216,1515804205660,19 -18217,1515804228462,20 -18218,1515804250596,21 -18219,1515804350631,22 -18220,1515804447179,22 -18221,1515804459703,22 -18222,1515804484807,26 -18223,1515804541052,27 -18224,1515804704675,27 -18225,1515804913009,26 -18226,1515805125239,26 -18227,1515805287450,25 -18228,1515805419827,25 -18229,1515805512310,24 -18230,1515805629090,24 -18231,1515805708597,24 -18232,1515805767777,24 -18233,1515805830301,24 -18234,1515805919800,23 -18235,1515805980316,24 -18236,1515806009160,23 -18237,1515806077738,24 -18238,1515806151895,25 -18239,1515806188334,25 -18240,1515806292511,26 -18241,1515806492313,25 -18242,1515806618301,24 -18243,1515806648089,24 -18244,1515806695582,26 -18245,1515806732528,26 -18246,1515806781923,26 -18247,1515806830772,26 -18248,1515806886773,27 -18249,1515806976892,28 -18250,1515807090247,28 -18251,1515807217405,27 -18252,1515807332284,27 -18253,1515807391287,26 -18254,1515807423882,26 -18255,1515807473605,28 -18256,1515807513287,28 -18257,1515807606372,28 -18258,1515807728662,29 -18259,1515807774248,28 -18260,1515807910720,28 -18261,1515808045585,27 -18262,1515808139513,27 -18263,1515808242779,27 -18264,1515808390781,26 -18265,1515808493758,26 -18266,1515808602179,25 -18267,1515808747989,24 -18268,1515808828862,23 -18269,1515808918527,24 -18270,1515809005654,23 -18271,1515809050605,22 -18272,1515809076199,23 -18273,1515809101891,24 -18274,1515809167926,24 -18275,1515809225434,25 -18276,1515809293148,25 -18277,1515809362956,25 -18278,1515809375168,25 -18279,1515809490239,28 -18280,1515809601645,28 -18281,1515809780021,27 -18282,1515810001291,27 -18283,1515810085106,27 -18284,1515810104364,26 -18285,1515810123156,29 -18286,1515810145173,30 -18287,1515810178031,33 -18288,1515810253486,34 -18289,1515810538713,33 -18290,1515810770655,33 -18291,1515810779352,32 -18292,1515810933263,40 -18293,1515811216956,39 -18294,1515811417492,39 -18295,1515811479583,38 -18296,1515811605383,38 -18297,1515811721142,37 -18298,1515811770570,37 -18299,1515812057337,37 -18300,1515812364523,36 -18301,1515812434707,37 -18302,1515812530540,36 -18303,1515812628039,36 -18304,1515812697445,36 -18305,1515812795706,36 -18306,1515812942423,36 -18307,1515813046000,35 -18308,1515813116871,34 -18309,1515813285622,34 -18310,1515813412796,33 -18311,1515813459120,32 -18312,1515813514896,32 -18313,1515813615214,33 -18314,1515813718353,31 -18315,1515813818602,31 -18316,1515813935530,30 -18317,1515814073079,29 -18318,1515814206220,29 -18319,1515814296218,29 -18320,1515814349592,28 -18321,1515814395092,28 -18322,1515814453699,30 -18323,1515814486187,31 -18324,1515814580246,33 -18325,1515814646486,31 -18326,1515814727315,31 -18327,1515814863301,31 -18328,1515814990400,30 -18329,1515815126814,29 -18330,1515815236024,29 -18331,1515815301918,26 -18332,1515815338698,27 -18333,1515815430405,26 -18334,1515815506185,27 -18335,1515815673047,26 -18336,1515815806221,26 -18337,1515815828684,26 -18338,1515815912324,27 -18339,1515816015907,27 -18340,1515816063969,27 -18341,1515816116983,27 -18342,1515816199391,26 -18343,1515816245311,25 -18344,1515816317476,26 -18345,1515816371565,26 -18346,1515816413436,26 -18347,1515816494682,27 -18348,1515816584268,26 -18349,1515816692093,26 -18350,1515816862950,25 -18351,1515816999774,24 -18352,1515817033066,23 -18353,1515817085149,24 -18354,1515817182045,23 -18355,1515817241177,23 -18356,1515817296848,23 -18357,1515817370264,23 -18358,1515817419393,23 -18359,1515817448321,22 -18360,1515817602911,23 -18361,1515817695662,22 -18362,1515817812068,22 -18363,1515817881757,20 -18364,1515817966389,20 -18365,1515818166125,19 -18366,1515818312281,18 -18367,1515818340964,17 -18368,1515818376887,17 -18369,1515818419545,16 -18370,1515818482848,17 -18371,1515818534805,15 -18372,1515818557484,15 -18373,1515818583781,16 -18374,1515818615749,17 -18375,1515818641355,17 -18376,1515818670173,18 -18377,1515818699171,17 -18378,1515818817968,18 -18379,1515818941532,19 -18380,1515819017430,18 -18381,1515819126717,17 -18382,1515819197520,16 -18383,1515819243149,15 -18384,1515819326640,15 -18385,1515819396506,16 -18386,1515819435846,17 -18387,1515819486349,18 -18388,1515819550037,19 -18389,1515819620095,18 -18390,1515819672927,18 -18391,1515819725192,17 -18392,1515819765518,21 -18393,1515819787812,21 -18394,1515819813843,22 -18395,1515819910301,22 -18396,1515820013051,23 -18397,1515820092199,23 -18398,1515820282197,22 -18399,1515820425722,22 -18400,1515820475362,21 -18401,1515820571317,21 -18402,1515820660635,20 -18403,1515820736442,20 -18404,1515820842590,20 -18405,1515820912708,20 -18406,1515820942158,19 -18407,1515821057416,20 -18408,1515821133420,19 -18409,1515821184525,20 -18410,1515821210356,19 -18411,1515821222406,20 -18412,1515821305173,23 -18413,1515821314206,23 -18414,1515821396749,28 -18415,1515821462629,28 -18416,1515821508487,28 -18417,1515821652798,28 -18418,1515821862585,27 -18419,1515821979915,26 -18420,1515822106882,26 -18421,1515822199584,26 -18422,1515822349922,26 -18423,1515822593615,25 -18424,1515822703594,25 -18425,1515822757979,25 -18426,1515822887800,25 -18427,1515822981585,24 -18428,1515823117041,24 -18429,1515823303786,23 -18430,1515823484821,22 -18431,1515823635309,21 -18432,1515823754673,21 -18433,1515823884598,21 -18434,1515824018977,20 -18435,1515824127013,19 -18436,1515824207214,19 -18437,1515824277697,19 -18438,1515824309725,19 -18439,1515824376493,20 -18440,1515824605434,19 -18441,1515824814689,19 -18442,1515824844679,18 -18443,1515824981804,19 -18444,1515825098535,19 -18445,1515825131552,18 -18446,1515825173200,19 -18447,1515825253018,19 -18448,1515825340105,19 -18449,1515825419200,19 -18450,1515825568908,18 -18451,1515825698001,18 -18452,1515825730096,16 -18453,1515825788729,17 -18454,1515825848161,17 -18455,1515825857061,17 -18456,1515825933557,21 -18457,1515826081439,20 -18458,1515826207656,20 -18459,1515826274990,20 -18460,1515826388056,20 -18461,1515826502436,20 -18462,1515826583374,18 -18463,1515826647244,18 -18464,1515826692709,18 -18465,1515826767455,17 -18466,1515826827387,17 -18467,1515826878453,17 -18468,1515826948720,17 -18469,1515827000942,17 -18470,1515827088371,16 -18471,1515827250897,16 -18472,1515827355079,16 -18473,1515827418859,15 -18474,1515827457813,15 -18475,1515827500929,15 -18476,1515827577770,16 -18477,1515827674188,16 -18478,1515827852110,16 -18479,1515828026925,15 -18480,1515828066877,15 -18481,1515828102500,14 -18482,1515828154969,14 -18483,1515828184457,14 -18484,1515828209719,14 -18485,1515828242000,15 -18486,1515828267740,15 -18487,1515828303678,16 -18488,1515828332120,16 -18489,1515828367908,17 -18490,1515828404411,16 -18491,1515828416503,17 -18492,1515828425935,19 -18493,1515828483595,24 -18494,1515828536399,25 -18495,1515828616144,25 -18496,1515828692642,25 -18497,1515828768918,25 -18498,1515828791487,24 -18499,1515828834329,25 -18500,1515828968655,26 -18501,1515829130481,26 -18502,1515829211555,24 -18503,1515829278143,25 -18504,1515829358306,24 -18505,1515829421411,24 -18506,1515829480564,24 -18507,1515829537135,24 -18508,1515829566148,24 -18509,1515829652444,24 -18510,1515829752049,24 -18511,1515829875635,25 -18512,1515830022118,26 -18513,1515830115534,25 -18514,1515830161020,28 -18515,1515830202004,29 -18516,1515830237283,30 -18517,1515830269137,31 -18518,1515830460499,32 -18519,1515830713200,31 -18520,1515830836162,31 -18521,1515830888910,30 -18522,1515830978259,30 -18523,1515831037920,30 -18524,1515831073055,30 -18525,1515831162831,31 -18526,1515831276453,31 -18527,1515831457559,31 -18528,1515831626075,30 -18529,1515831657764,29 -18530,1515831693538,30 -18531,1515831746850,32 -18532,1515832002331,32 -18533,1515832372000,31 -18534,1515832563762,30 -18535,1515832643860,29 -18536,1515832765762,29 -18537,1515832846448,28 -18538,1515832926861,28 -18539,1515833010529,28 -18540,1515833050612,28 -18541,1515833101038,28 -18542,1515833147639,27 -18543,1515833205026,29 -18544,1515833254159,28 -18545,1515833290647,29 -18546,1515833350563,30 -18547,1515833442043,30 -18548,1515833537966,30 -18549,1515833641265,29 -18550,1515833709625,28 -18551,1515833728205,28 -18552,1515833797696,31 -18553,1515833907608,31 -18554,1515834014019,30 -18555,1515834186407,29 -18556,1515834321908,31 -18557,1515834381486,30 -18558,1515834608281,30 -18559,1515834918197,29 -18560,1515835045705,28 -18561,1515835088722,27 -18562,1515835264913,28 -18563,1515835460129,27 -18564,1515835545323,25 -18565,1515835651115,26 -18566,1515835751280,25 -18567,1515835811388,24 -18568,1515835885138,24 -18569,1515835951013,23 -18570,1515836019693,23 -18571,1515836082852,23 -18572,1515836125935,22 -18573,1515836171493,22 -18574,1515836210415,21 -18575,1515836236590,22 -18576,1515836249667,23 -18577,1515836319331,26 -18578,1515836625188,25 -18579,1515836963118,24 -18580,1515837054830,23 -18581,1515837065357,22 -18582,1515837122024,26 -18583,1515837177876,25 -18584,1515837237601,26 -18585,1515837344541,26 -18586,1515837454284,26 -18587,1515837632965,25 -18588,1515837794667,24 -18589,1515837874147,24 -18590,1515837930073,22 -18591,1515838004409,22 -18592,1515838079979,23 -18593,1515838095910,26 -18594,1515838114816,28 -18595,1515838197798,30 -18596,1515838308844,30 -18597,1515838349415,29 -18598,1515838490672,30 -18599,1515838734332,30 -18600,1515838863298,30 -18601,1515838952601,28 -18602,1515839075625,28 -18603,1515839144414,28 -18604,1515839193354,27 -18605,1515839310758,28 -18606,1515839427826,26 -18607,1515839590581,27 -18608,1515839756397,25 -18609,1515839876667,25 -18610,1515839986970,24 -18611,1515840063248,24 -18612,1515840131841,24 -18613,1515840140851,23 -18614,1515840176634,27 -18615,1515840185186,29 -18616,1515840271503,36 -18617,1515840340486,36 -18618,1515840455109,37 -18619,1515840476871,37 -18620,1515840516416,39 -18621,1515840623812,40 -18622,1515840776728,40 -18623,1515840901536,39 -18624,1515840963922,38 -18625,1515841003249,40 -18626,1515841053241,40 -18627,1515841091734,41 -18628,1515841118460,41 -18629,1515841481035,44 -18630,1515841938600,43 -18631,1515842055224,42 -18632,1515842381770,42 -18633,1515842673134,41 -18634,1515842860362,39 -18635,1515843224946,38 -18636,1515843686852,37 -18637,1515843903974,35 -18638,1515843984571,35 -18639,1515844081312,35 -18640,1515844112849,34 -18641,1515844158824,36 -18642,1515844220130,36 -18643,1515844312097,36 -18644,1515844419989,37 -18645,1515844565503,35 -18646,1515844768843,36 -18647,1515844858450,35 -18648,1515844903503,35 -18649,1515844976425,35 -18650,1515845023291,34 -18651,1515845096965,35 -18652,1515845178832,36 -18653,1515845278891,36 -18654,1515845393802,35 -18655,1515845431190,35 -18656,1515845662677,35 -18657,1515845910969,33 -18658,1515845940268,33 -18659,1515846114504,34 -18660,1515846334787,32 -18661,1515846411474,32 -18662,1515846535299,32 -18663,1515846644354,30 -18664,1515846754266,29 -18665,1515846762339,29 -18666,1515846843821,36 -18667,1515846848147,35 -18668,1515847236424,53 -18669,1515847564845,51 -18670,1515848079388,49 -18671,1515848233993,48 -18672,1515848347106,47 -18673,1515848460724,46 -18674,1515848501877,45 -18675,1515848622507,47 -18676,1515848791282,47 -18677,1515848897997,47 -18678,1515848985867,46 -18679,1515849090287,45 -18680,1515849250187,45 -18681,1515849426720,43 -18682,1515849538041,44 -18683,1515849783197,44 -18684,1515849945760,42 -18685,1515849953618,41 -18686,1515850020381,53 -18687,1515850111026,52 -18688,1515850225590,51 -18689,1515850332056,50 -18690,1515850478392,49 -18691,1515850751341,48 -18692,1515851101942,47 -18693,1515851208612,44 -18694,1515851292144,46 -18695,1515851364864,46 -18696,1515851469758,46 -18697,1515851787862,45 -18698,1515852136832,44 -18699,1515852182461,42 -18700,1515852276767,43 -18701,1515852366582,41 -18702,1515852663280,40 -18703,1515852759048,39 -18704,1515852863492,38 -18705,1515852896223,37 -18706,1515852925421,38 -18707,1515852937611,39 -18708,1515853004070,45 -18709,1515853080713,44 -18710,1515853103235,43 -18711,1515853115743,46 -18712,1515853200211,52 -18713,1515853325823,51 -18714,1515853363902,53 -18715,1515853433821,54 -18716,1515853976263,57 -18717,1515854512981,56 -18718,1515854566701,55 -18719,1515854670150,54 -18720,1515854784293,55 -18721,1515854863455,55 -18722,1515855063786,55 -18723,1515855243155,53 -18724,1515855308004,51 -18725,1515855505286,52 -18726,1515855520044,51 -18727,1515855567002,58 -18728,1515855639015,60 -18729,1515855717179,61 -18730,1515855883099,61 -18731,1515856045376,59 -18732,1515856076709,57 -18733,1515856182807,60 -18734,1515856316836,58 -18735,1515856476530,57 -18736,1515856630954,55 -18737,1515856754686,53 -18738,1515856907566,52 -18739,1515856993296,50 -18740,1515857137029,50 -18741,1515857328572,50 -18742,1515857547311,48 -18743,1515857777497,47 -18744,1515857946617,45 -18745,1515858063255,43 -18746,1515858122045,42 -18747,1515858233218,41 -18748,1515858356112,40 -18749,1515858435233,39 -18750,1515858451175,38 -18751,1515858472132,42 -18752,1515858694863,45 -18753,1515858749614,43 -18754,1515859006848,42 -18755,1515859273872,40 -18756,1515859348120,40 -18757,1515859501195,38 -18758,1515859571093,36 -18759,1515859685158,35 -18760,1515859754479,34 -18761,1515859767370,33 -18762,1515860076933,36 -18763,1515860460541,34 -18764,1515860625555,32 -18765,1515860656675,30 -18766,1515860719525,33 -18767,1515860796601,33 -18768,1515860937790,41 -18769,1515861098764,40 -18770,1515861325909,38 -18771,1515861534323,36 -18772,1515861803911,34 -18773,1515861886255,33 -18774,1515861890479,32 -18775,1515861905013,49 -18776,1515861970315,55 -18777,1515862072394,54 -18778,1515862083428,53 -18779,1515862183458,62 -18780,1515862798032,62 -18781,1515863446811,60 -18782,1515863576439,57 -18783,1515863730874,55 -18784,1515863895716,54 -18785,1515863910235,52 -18786,1515864010251,63 -18787,1515864078748,63 -18788,1515864209984,63 -18789,1515864271554,62 -18790,1515864556964,62 -18791,1515864820346,61 -18792,1515864984356,58 -18793,1515865134864,56 -18794,1515865406089,55 -18795,1515865659789,53 -18796,1515865690658,51 -18797,1515865803001,53 -18798,1515865880636,51 -18799,1515866014657,50 -18800,1515866466850,48 -18801,1515866525848,47 -18802,1515866711600,46 -18803,1515866998032,44 -18804,1515867167562,42 -18805,1515867367193,40 -18806,1515867617797,39 -18807,1515867645751,38 -18808,1515867736712,42 -18809,1515868034454,41 -18810,1515868489708,40 -18811,1515868982990,39 -18812,1515869034773,41 -18813,1515869039516,41 -18814,1515869190119,60 -18815,1515869434925,60 -18816,1515869728253,59 -18817,1515869917600,56 -18818,1515870291890,54 -18819,1515870566229,53 -18820,1515870660539,51 -18821,1515870771959,50 -18822,1515870959660,49 -18823,1515871193583,47 -18824,1515871316853,45 -18825,1515871514690,44 -18826,1515871705085,43 -18827,1515871836311,45 -18828,1515872019483,44 -18829,1515872157450,43 -18830,1515872309307,42 -18831,1515872385641,41 -18832,1515872400751,40 -18833,1515872519578,46 -18834,1515872677475,45 -18835,1515872765561,44 -18836,1515872832992,43 -18837,1515872935851,41 -18838,1515873265532,40 -18839,1515873592353,38 -18840,1515873639925,37 -18841,1515873844324,37 -18842,1515874018469,34 -18843,1515874090977,33 -18844,1515874177188,32 -18845,1515874267165,30 -18846,1515874406126,29 -18847,1515874604879,27 -18848,1515874767363,26 -18849,1515874881970,24 -18850,1515875043645,22 -18851,1515875176396,23 -18852,1515875321224,23 -18853,1515875400914,21 -18854,1515875480402,20 -18855,1515875516635,19 -18856,1515875560088,18 -18857,1515875588638,18 -18858,1515875633629,16 -18859,1515875641353,15 -18860,1515875650615,19 -18861,1515875716334,22 -18862,1515875734540,22 -18863,1515875767490,23 -18864,1515875810465,22 -18865,1515875870734,21 -18866,1515875971019,21 -18867,1515875975295,19 -18868,1515876030440,28 -18869,1515876100109,27 -18870,1515876122148,26 -18871,1515876244390,27 -18872,1515876395150,24 -18873,1515876472465,22 -18874,1515876522143,20 -18875,1515876526744,28 -18876,1515876535141,45 -18877,1515876589587,56 -18878,1515876661803,56 -18879,1515876713126,62 -18880,1515876911183,62 -18881,1515877219478,60 -18882,1515877852382,58 -18883,1515878338877,56 -18884,1515878449152,54 -18885,1515878572390,53 -18886,1515878649344,56 -18887,1515878728249,57 -18888,1515878814944,57 -18889,1515878918066,57 -18890,1515878973708,57 -18891,1515879046363,56 -18892,1515879331008,57 -18893,1515879697278,54 -18894,1515879866360,53 -18895,1515880047998,52 -18896,1515880161224,50 -18897,1515880229599,50 -18898,1515880395113,50 -18899,1515880490173,49 -18900,1515880590148,49 -18901,1515880758993,48 -18902,1515880930992,47 -18903,1515881034842,45 -18904,1515881170451,44 -18905,1515881395027,42 -18906,1515881618595,41 -18907,1515881761228,39 -18908,1515881915154,38 -18909,1515882087720,37 -18910,1515882298932,36 -18911,1515882411971,34 -18912,1515882465197,33 -18913,1515882473114,32 -18914,1515882544888,51 -18915,1515882708314,50 -18916,1515882875803,48 -18917,1515883045739,48 -18918,1515883082055,46 -18919,1515883093604,47 -18920,1515883180604,55 -18921,1515883202019,55 -18922,1515883343604,58 -18923,1515883515755,57 -18924,1515883753055,56 -18925,1515884073522,54 -18926,1515884298564,53 -18927,1515884461388,51 -18928,1515884668794,50 -18929,1515884896538,47 -18930,1515885043492,46 -18931,1515885099118,45 -18932,1515885123298,44 -18933,1515885211644,49 -18934,1515885255924,49 -18935,1515885313118,49 -18936,1515885328881,50 -18937,1515885415874,55 -18938,1515885563487,54 -18939,1515886019264,53 -18940,1515886309756,51 -18941,1515886634946,49 -18942,1515886742119,47 -18943,1515886836605,46 -18944,1515887028606,45 -18945,1515887225755,43 -18946,1515887312640,41 -18947,1515887426034,40 -18948,1515887481669,38 -18949,1515887590908,38 -18950,1515888012306,36 -18951,1515888369905,34 -18952,1515888419945,31 -18953,1515888707731,31 -18954,1515889080771,28 -18955,1515889085251,25 -18956,1515889168037,37 -18957,1515889254670,36 -18958,1515889326485,35 -18959,1515889421629,34 -18960,1515889495311,34 -18961,1515889589123,35 -18962,1515889600407,33 -18963,1515889728325,38 -18964,1515889885321,37 -18965,1515889968728,36 -18966,1515890214431,34 -18967,1515890457636,32 -18968,1515890486621,35 -18969,1515890627535,36 -18970,1515890867161,35 -18971,1515890919942,34 -18972,1515891032646,32 -18973,1515891098179,31 -18974,1515891105841,29 -18975,1515891147009,37 -18976,1515891269339,44 -18977,1515891388358,48 -18978,1515891445514,48 -18979,1515891472759,49 -18980,1515891507916,52 -18981,1515891645329,54 -18982,1515891777419,53 -18983,1515891979935,51 -18984,1515892083325,49 -18985,1515892202135,48 -18986,1515892257227,47 -18987,1515892324384,48 -18988,1515892364105,48 -18989,1515892439971,49 -18990,1515892778806,49 -18991,1515893085597,48 -18992,1515893104668,47 -18993,1515893187110,50 -18994,1515893278857,49 -18995,1515893283243,48 -18996,1515893500126,73 -18997,1515893504562,71 -18998,1515893777046,107 -18999,1515893947698,106 -19000,1515894429990,104 -19001,1515894713527,102 -19002,1515895292383,99 -19003,1515895731894,96 -19004,1515896151075,94 -19005,1515896856488,91 -19006,1515897247650,88 -19007,1515897312591,86 -19008,1515897484646,85 -19009,1515897499817,83 -19010,1515897560115,93 -19011,1515897617418,94 -19012,1515897901667,94 -19013,1515898311159,92 -19014,1515898627003,93 -19015,1515899079430,92 -19016,1515899669208,89 -19017,1515900343729,86 -19018,1515900893785,83 -19019,1515900956676,81 -19020,1515901283817,86 -19021,1515901582054,83 -19022,1515901690848,83 -19023,1515901879310,82 -19024,1515901971027,81 -19025,1515902212162,80 -19026,1515902515031,77 -19027,1515902795037,74 -19028,1515903049828,72 -19029,1515903118814,70 -19030,1515903203106,68 -19031,1515903470331,67 -19032,1515903711407,65 -19033,1515903850314,65 -19034,1515903973227,63 -19035,1515904099868,62 -19036,1515904393439,61 -19037,1515904664166,62 -19038,1515904918395,61 -19039,1515905049615,59 -19040,1515905181079,56 -19041,1515905229760,55 -19042,1515905245552,54 -19043,1515905338333,59 -19044,1515905482380,58 -19045,1515905681977,55 -19046,1515905872048,53 -19047,1515905982698,51 -19048,1515906107778,49 -19049,1515906288250,47 -19050,1515906347075,45 -19051,1515906423177,43 -19052,1515906517601,41 -19053,1515906808175,40 -19054,1515906826132,37 -19055,1515906866118,39 -19056,1515906894950,45 -19057,1515906954759,45 -19058,1515907156157,44 -19059,1515907170602,41 -19060,1515907312211,45 -19061,1515907509391,44 -19062,1515907610524,41 -19063,1515907686949,42 -19064,1515907769225,40 -19065,1515907780585,38 -19066,1515907822301,43 -19067,1515907867782,43 -19068,1515907936953,41 -19069,1515908089526,40 -19070,1515908245955,38 -19071,1515908373576,35 -19072,1515908508487,33 -19073,1515908667789,30 -19074,1515908755514,28 -19075,1515908870443,30 -19076,1515908963286,28 -19077,1515909072330,26 -19078,1515909120619,23 -19079,1515909191343,22 -19080,1515909295856,22 -19081,1515909364835,20 -19082,1515909392689,19 -19083,1515909450435,17 -19084,1515909521461,16 -19085,1515909549818,13 -19086,1515909569580,12 -19087,1515909598720,11 -19088,1515909624730,9 -19089,1515909643959,8 -19090,1515909744040,7 -19091,1515909786836,4 -19092,1515909821866,1 -19093,1515909830656,1 -19094,1515909842591,1 -19095,1515909851914,1 -19096,1515909861186,8 -19097,1515909887268,7 -19098,1515909905811,25 -19099,1515909938647,26 -19100,1515909984246,27 -19101,1515909995331,27 -19102,1515910030123,30 -19103,1515910081478,30 -19104,1515910146909,30 -19105,1515910180242,29 -19106,1515910212386,29 -19107,1515910268957,29 -19108,1515910372854,29 -19109,1515910442120,29 -19110,1515910503361,34 -19111,1515910586649,35 -19112,1515910754080,36 -19113,1515910934187,34 -19114,1515910958833,33 -19115,1515910973333,35 -19116,1515911110972,39 -19117,1515911246420,37 -19118,1515911301551,36 -19119,1515911351103,36 -19120,1515911372402,37 -19121,1515911452281,39 -19122,1515911600721,38 -19123,1515911695361,38 -19124,1515911712844,37 -19125,1515911735328,41 -19126,1515911867623,44 -19127,1515912006998,42 -19128,1515912058956,41 -19129,1515912286483,41 -19130,1515912626116,40 -19131,1515912837625,39 -19132,1515912910262,38 -19133,1515913002964,37 -19134,1515913424284,36 -19135,1515913870088,35 -19136,1515913921614,33 -19137,1515913991780,33 -19138,1515914017533,32 -19139,1515914107611,32 -19140,1515914195681,32 -19141,1515914255356,31 -19142,1515914358145,31 -19143,1515914625027,34 -19144,1515914889530,33 -19145,1515915069557,32 -19146,1515915204461,30 -19147,1515915246922,29 -19148,1515915315934,29 -19149,1515915406193,28 -19150,1515915466839,27 -19151,1515915519464,26 -19152,1515915602713,26 -19153,1515915713769,26 -19154,1515915788988,24 -19155,1515915814475,25 -19156,1515915954939,27 -19157,1515915979247,27 -19158,1515915990244,28 -19159,1515916045382,33 -19160,1515916124527,36 -19161,1515916177726,35 -19162,1515916233654,35 -19163,1515916329571,35 -19164,1515916433094,35 -19165,1515916586219,34 -19166,1515916611363,36 -19167,1515916626421,39 -19168,1515916658784,44 -19169,1515916717824,47 -19170,1515917070300,46 -19171,1515917421008,45 -19172,1515917439425,44 -19173,1515917482030,48 -19174,1515917528108,48 -19175,1515917550614,49 -19176,1515917630127,52 -19177,1515917668718,52 -19178,1515917863921,54 -19179,1515918072075,52 -19180,1515918124880,51 -19181,1515918129210,51 -19182,1515918345254,77 -19183,1515918578728,76 -19184,1515918669267,75 -19185,1515918857981,74 -19186,1515919016344,73 -19187,1515919096084,72 -19188,1515919182433,72 -19189,1515919256256,72 -19190,1515919312448,72 -19191,1515919501496,72 -19192,1515919765819,70 -19193,1515920002299,68 -19194,1515920475399,65 -19195,1515920907983,63 -19196,1515921128520,61 -19197,1515921184412,60 -19198,1515921346938,60 -19199,1515921498985,59 -19200,1515921545486,59 -19201,1515921771189,59 -19202,1515922119024,60 -19203,1515922280787,58 -19204,1515922643853,58 -19205,1515922960144,55 -19206,1515923345601,54 -19207,1515923487298,53 -19208,1515923627194,52 -19209,1515923769940,51 -19210,1515923869604,49 -19211,1515924227781,48 -19212,1515924513763,46 -19213,1515924555386,44 -19214,1515924559956,45 -19215,1515924735829,67 -19216,1515924893515,68 -19217,1515924898113,66 -19218,1515926252447,98 -19219,1515926651605,96 -19220,1515927250222,93 -19221,1515927800647,93 -19222,1515928487528,90 -19223,1515928864249,88 -19224,1515928956888,85 -19225,1515929085444,87 -19226,1515929276439,87 -19227,1515929365438,86 -19228,1515929416185,85 -19229,1515929465878,87 -19230,1515929644304,88 -19231,1515929868870,86 -19232,1515930132508,83 -19233,1515930365459,82 -19234,1515930623164,79 -19235,1515930780845,77 -19236,1515930909034,75 -19237,1515931092500,74 -19238,1515931338450,72 -19239,1515931571656,71 -19240,1515931715230,69 -19241,1515931751067,66 -19242,1515931822285,68 -19243,1515931918134,67 -19244,1515932037178,66 -19245,1515932120767,64 -19246,1515932146898,62 -19247,1515932378971,65 -19248,1515932681822,63 -19249,1515932896210,60 -19250,1515932957888,57 -19251,1515933197165,57 -19252,1515933550105,55 -19253,1515933695982,51 -19254,1515933738396,49 -19255,1515934047656,48 -19256,1515934103983,46 -19257,1515934189573,46 -19258,1515934329074,44 -19259,1515934402586,44 -19260,1515934459492,43 -19261,1515934594204,43 -19262,1515934731913,40 -19263,1515934811302,38 -19264,1515934910003,36 -19265,1515935027169,34 -19266,1515935076646,31 -19267,1515935176545,31 -19268,1515935264489,31 -19269,1515935290224,31 -19270,1515935352244,32 -19271,1515935414717,30 -19272,1515935499808,28 -19273,1515935514487,28 -19274,1515935573789,30 -19275,1515935622352,29 -19276,1515935669339,30 -19277,1515935735937,29 -19278,1515935845553,29 -19279,1515935980346,27 -19280,1515936043097,24 -19281,1515936121656,23 -19282,1515936218951,35 -19283,1515936271144,33 -19284,1515936282452,33 -19285,1515936304864,38 -19286,1515936334188,39 -19287,1515936453808,40 -19288,1515936718311,39 -19289,1515936760335,38 -19290,1515936816052,38 -19291,1515936885933,38 -19292,1515936990596,37 -19293,1515937042774,36 -19294,1515937144662,35 -19295,1515937187978,33 -19296,1515937204252,32 -19297,1515937270065,34 -19298,1515937326515,34 -19299,1515937532600,33 -19300,1515937547357,31 -19301,1515937613629,34 -19302,1515937628205,32 -19303,1515937658071,35 -19304,1515937747403,36 -19305,1515937813358,33 -19306,1515937896846,32 -19307,1515937935499,29 -19308,1515938002208,29 -19309,1515938071215,27 -19310,1515938140961,25 -19311,1515938266143,24 -19312,1515938381480,21 -19313,1515938437977,19 -19314,1515938461301,18 -19315,1515938487462,28 -19316,1515938564902,29 -19317,1515938654743,27 -19318,1515938714910,42 -19319,1515938769732,43 -19320,1515938798754,42 -19321,1515938888618,43 -19322,1515938964189,42 -19323,1515939041979,41 -19324,1515939053256,41 -19325,1515939084004,48 -19326,1515939149158,50 -19327,1515939236970,50 -19328,1515939348649,50 -19329,1515939411018,50 -19330,1515939428756,52 -19331,1515939467550,57 -19332,1515939541003,58 -19333,1515939605242,58 -19334,1515939661959,59 -19335,1515939840596,58 -19336,1515940086478,57 -19337,1515940335912,56 -19338,1515940540065,54 -19339,1515940674593,52 -19340,1515941070844,51 -19341,1515941499780,49 -19342,1515941557739,49 -19343,1515941585752,50 -19344,1515941657382,52 -19345,1515941726281,52 -19346,1515941740411,52 -19347,1515941802803,61 -19348,1515941817307,61 -19349,1515941869637,69 -19350,1515942002962,70 -19351,1515942058153,69 -19352,1515942092545,69 -19353,1515942277302,71 -19354,1515942492255,70 -19355,1515942599748,69 -19356,1515943008243,68 -19357,1515943380043,66 -19358,1515943439621,65 -19359,1515943747960,65 -19360,1515944052761,63 -19361,1515944423664,61 -19362,1515944931272,59 -19363,1515945433088,57 -19364,1515945498887,55 -19365,1515945587790,55 -19366,1515945602759,54 -19367,1515945839188,59 -19368,1515946658339,58 -19369,1515947471137,56 -19370,1515947719629,54 -19371,1515947765997,52 -19372,1515947895062,53 -19373,1515948096424,51 -19374,1515948224195,51 -19375,1515948275017,49 -19376,1515948353929,49 -19377,1515948480043,49 -19378,1515948687332,48 -19379,1515948705212,45 -19380,1515948864021,49 -19381,1515948922049,47 -19382,1515948994398,46 -19383,1515949087970,45 -19384,1515949199703,44 -19385,1515949300089,46 -19386,1515949364996,46 -19387,1515949470451,46 -19388,1515949585958,45 -19389,1515949800482,43 -19390,1515950021254,41 -19391,1515950107271,40 -19392,1515950131871,39 -19393,1515950422884,40 -19394,1515950727961,38 -19395,1515950778317,36 -19396,1515950800647,36 -19397,1515950877688,39 -19398,1515950954742,38 -19399,1515951052432,37 -19400,1515951164024,36 -19401,1515951311501,36 -19402,1515951473436,35 -19403,1515951643499,35 -19404,1515951713102,35 -19405,1515951762187,33 -19406,1515951835087,33 -19407,1515951839359,32 -19408,1515951873878,48 -19409,1515951913316,49 -19410,1515952052098,50 -19411,1515952111289,48 -19412,1515952314023,47 -19413,1515952670893,45 -19414,1515952894229,42 -19415,1515953177528,41 -19416,1515953269938,39 -19417,1515953316377,38 -19418,1515953436931,37 -19419,1515953471299,36 -19420,1515953527516,37 -19421,1515953579751,36 -19422,1515953659788,36 -19423,1515953789261,35 -19424,1515953897577,33 -19425,1515953952814,35 -19426,1515954011093,36 -19427,1515954054066,36 -19428,1515954235275,35 -19429,1515954416165,34 -19430,1515954536224,33 -19431,1515954629990,34 -19432,1515954662373,35 -19433,1515954758374,35 -19434,1515954862354,34 -19435,1515954927847,34 -19436,1515955032885,33 -19437,1515955203350,32 -19438,1515955309969,30 -19439,1515955603917,27 -19440,1515955838821,26 -19441,1515955908324,24 -19442,1515955936403,22 -19443,1515956020585,23 -19444,1515956100248,23 -19445,1515956125646,22 -19446,1515956261685,22 -19447,1515956502983,25 -19448,1515956620559,24 -19449,1515956646941,27 -19450,1515956716745,29 -19451,1515956897886,29 -19452,1515956925437,29 -19453,1515957021532,31 -19454,1515957170543,30 -19455,1515957283394,29 -19456,1515957468592,28 -19457,1515957678547,26 -19458,1515957835493,25 -19459,1515958000076,25 -19460,1515958268460,23 -19461,1515958508729,22 -19462,1515958632723,20 -19463,1515958643705,18 -19464,1515958705385,21 -19465,1515958766602,20 -19466,1515958778672,20 -19467,1515958860901,26 -19468,1515958885507,25 -19469,1515958917665,25 -19470,1515958933930,25 -19471,1515958955368,27 -19472,1515959028826,29 -19473,1515959173275,29 -19474,1515959297363,28 -19475,1515959342581,26 -19476,1515959347063,27 -19477,1515959364723,39 -19478,1515959399042,43 -19479,1515959455011,44 -19480,1515959548798,47 -19481,1515959573541,46 -19482,1515959595099,49 -19483,1515959641000,53 -19484,1515959778051,54 -19485,1515959823451,53 -19486,1515959953643,53 -19487,1515960214997,53 -19488,1515960422224,51 -19489,1515960539750,50 -19490,1515960644589,49 -19491,1515960734235,48 -19492,1515960824660,47 -19493,1515961053696,48 -19494,1515961325318,46 -19495,1515961469724,45 -19496,1515961868549,43 -19497,1515962336952,43 -19498,1515962563088,41 -19499,1515962679053,40 -19500,1515962917969,39 -19501,1515962989760,37 -19502,1515963140569,36 -19503,1515963250484,35 -19504,1515963347657,33 -19505,1515963440903,33 -19506,1515963516417,32 -19507,1515963747876,31 -19508,1515963976881,39 -19509,1515964057638,38 -19510,1515964106704,39 -19511,1515964206428,40 -19512,1515964302799,40 -19513,1515964333804,38 -19514,1515964417469,39 -19515,1515964490544,39 -19516,1515964566958,38 -19517,1515964865050,37 -19518,1515965149136,37 -19519,1515965217265,35 -19520,1515965312086,36 -19521,1515965456360,35 -19522,1515965512930,35 -19523,1515965669491,36 -19524,1515965829542,34 -19525,1515965845960,32 -19526,1515965850710,36 -19527,1515965910518,53 -19528,1515965955794,54 -19529,1515966022560,55 -19530,1515966140764,54 -19531,1515966276580,54 -19532,1515966326244,53 -19533,1515966446202,55 -19534,1515966550448,53 -19535,1515966615007,52 -19536,1515966639806,53 -19537,1515966688633,55 -19538,1515966775119,56 -19539,1515967090975,56 -19540,1515967382338,54 -19541,1515967434701,51 -19542,1515967460377,51 -19543,1515967476966,55 -19544,1515967583949,61 -19545,1515967755631,60 -19546,1515967839476,59 -19547,1515967976404,59 -19548,1515968321952,57 -19549,1515968357211,54 -19550,1515968438803,57 -19551,1515968604578,56 -19552,1515968737458,54 -19553,1515968955085,53 -19554,1515969188036,52 -19555,1515969308672,50 -19556,1515969424242,49 -19557,1515969498634,47 -19558,1515969580892,46 -19559,1515969649739,45 -19560,1515969684166,43 -19561,1515969728816,44 -19562,1515969801132,44 -19563,1515969805622,42 -19564,1515970099450,64 -19565,1515970263340,62 -19566,1515970504478,60 -19567,1515970643399,60 -19568,1515970864549,57 -19569,1515971116079,56 -19570,1515971261965,55 -19571,1515971273088,55 -19572,1515971294331,64 -19573,1515971586052,70 -19574,1515971877002,67 -19575,1515971919416,65 -19576,1515972003761,65 -19577,1515972021920,72 -19578,1515972114633,80 -19579,1515972327411,81 -19580,1515972627109,80 -19581,1515972915205,78 -19582,1515973144215,78 -19583,1515973452806,78 -19584,1515973784612,77 -19585,1515974081581,75 -19586,1515974291773,75 -19587,1515974607922,73 -19588,1515974887954,71 -19589,1515975372737,69 -19590,1515975786709,67 -19591,1515976146864,65 -19592,1515976466526,63 -19593,1515976806973,61 -19594,1515977121681,59 -19595,1515977534369,57 -19596,1515977902384,55 -19597,1515978101912,52 -19598,1515978353576,50 -19599,1515978433742,47 -19600,1515978459448,46 -19601,1515978678961,48 -19602,1515978775760,46 -19603,1515978828604,45 -19604,1515978972737,44 -19605,1515979376773,43 -19606,1515979742930,40 -19607,1515979859259,38 -19608,1515980022674,36 -19609,1515980223166,34 -19610,1515980399049,32 -19611,1515980506881,30 -19612,1515980535986,29 -19613,1515980610693,29 -19614,1515980665102,28 -19615,1515980677204,26 -19616,1515980686327,29 -19617,1515980772896,35 -19618,1515980889374,33 -19619,1515980988036,30 -19620,1515981000696,29 -19621,1515981068872,32 -19622,1515981148340,30 -19623,1515981322527,29 -19624,1515981330889,26 -19625,1515981350084,31 -19626,1515981376084,33 -19627,1515981387223,43 -19628,1515981422139,50 -19629,1515981457143,52 -19630,1515981575066,54 -19631,1515981689643,51 -19632,1515981749456,50 -19633,1515981955062,50 -19634,1515982147867,48 -19635,1515982204143,46 -19636,1515982300837,46 -19637,1515982407825,47 -19638,1515982458756,46 -19639,1515982643977,46 -19640,1515982835424,44 -19641,1515983028601,42 -19642,1515983344428,40 -19643,1515983408499,40 -19644,1515983480781,42 -19645,1515983614286,42 -19646,1515983877617,40 -19647,1515984111551,38 -19648,1515984237070,37 -19649,1515984353858,34 -19650,1515984436744,34 -19651,1515984466098,34 -19652,1515984679817,34 -19653,1515984914109,32 -19654,1515984966435,30 -19655,1515985006039,29 -19656,1515985040859,28 -19657,1515985193955,28 -19658,1515985315609,27 -19659,1515985331332,25 -19660,1515985358881,26 -19661,1515985411277,28 -19662,1515985453433,27 -19663,1515985516819,27 -19664,1515985524850,36 -19665,1515985555775,45 -19666,1515985714878,47 -19667,1515985926769,44 -19668,1515986176336,42 -19669,1515986410410,40 -19670,1515986516043,38 -19671,1515986586016,37 -19672,1515986635094,42 -19673,1515986695042,45 -19674,1515986737452,45 -19675,1515986770940,45 -19676,1515986854121,48 -19677,1515986925710,48 -19678,1515987059198,52 -19679,1515987152059,52 -19680,1515987362751,50 -19681,1515987644936,50 -19682,1515987766953,48 -19683,1515987842885,47 -19684,1515987905808,46 -19685,1515987938776,46 -19686,1515988016600,47 -19687,1515988108723,47 -19688,1515988223936,46 -19689,1515988376278,45 -19690,1515988513478,43 -19691,1515988664871,42 -19692,1515988764436,40 -19693,1515988874230,39 -19694,1515989022957,38 -19695,1515989088089,36 -19696,1515989240228,35 -19697,1515989473509,33 -19698,1515989560146,31 -19699,1515989608736,30 -19700,1515989655795,30 -19701,1515989760874,30 -19702,1515989787185,29 -19703,1515989836951,31 -19704,1515989900205,30 -19705,1515989939715,30 -19706,1515989985265,28 -19707,1515990041106,28 -19708,1515990121424,27 -19709,1515990236674,25 -19710,1515990261191,23 -19711,1515990289724,23 -19712,1515990300574,23 -19713,1515990326566,28 -19714,1515990379536,28 -19715,1515990421823,27 -19716,1515990477383,28 -19717,1515990552625,31 -19718,1515990706295,29 -19719,1515990848683,29 -19720,1515990871059,26 -19721,1515990914275,30 -19722,1515990946979,30 -19723,1515991006768,29 -19724,1515991072523,28 -19725,1515991156852,31 -19726,1515991268489,31 -19727,1515991339746,31 -19728,1515991433887,35 -19729,1515991628696,36 -19730,1515991783870,36 -19731,1515991840664,35 -19732,1515991868409,35 -19733,1515991923754,36 -19734,1515991982421,36 -19735,1515992069505,35 -19736,1515992161624,35 -19737,1515992228635,35 -19738,1515992282359,34 -19739,1515992381351,36 -19740,1515992520229,35 -19741,1515992577966,33 -19742,1515992705833,33 -19743,1515992906833,32 -19744,1515993042607,30 -19745,1515993139329,29 -19746,1515993237753,28 -19747,1515993310677,27 -19748,1515993443292,26 -19749,1515993578731,25 -19750,1515993709065,23 -19751,1515993868313,22 -19752,1515993997654,22 -19753,1515994080850,21 -19754,1515994117615,19 -19755,1515994180036,19 -19756,1515994226982,19 -19757,1515994272965,19 -19758,1515994336554,18 -19759,1515994375301,17 -19760,1515994425423,18 -19761,1515994572150,17 -19762,1515994688909,17 -19763,1515994803345,16 -19764,1515994912990,15 -19765,1515995009847,19 -19766,1515995112652,19 -19767,1515995134785,18 -19768,1515995164459,19 -19769,1515995220031,18 -19770,1515995280894,18 -19771,1515995306767,17 -19772,1515995344439,18 -19773,1515995404933,18 -19774,1515995467803,18 -19775,1515995513948,19 -19776,1515995576076,19 -19777,1515995648772,19 -19778,1515995698983,19 -19779,1515995873638,18 -19780,1515996074006,18 -19781,1515996164086,17 -19782,1515996243687,16 -19783,1515996310371,15 -19784,1515996334576,14 -19785,1515996350924,15 -19786,1515996373722,17 -19787,1515996412664,18 -19788,1515996448419,19 -19789,1515996495436,19 -19790,1515996560842,19 -19791,1515996602932,18 -19792,1515996669209,17 -19793,1515996686893,18 -19794,1515996723318,19 -19795,1515996820503,19 -19796,1515996936879,18 -19797,1515997058958,17 -19798,1515997175532,16 -19799,1515997222149,15 -19800,1515997302129,15 -19801,1515997323365,15 -19802,1515997345926,15 -19803,1515997361550,17 -19804,1515997387647,18 -19805,1515997414456,19 -19806,1515997440790,20 -19807,1515997524664,21 -19808,1515997608553,20 -19809,1515997637477,20 -19810,1515997670031,20 -19811,1515997696015,21 -19812,1515997783187,22 -19813,1515997891256,24 -19814,1515997975894,24 -19815,1515998035193,24 -19816,1515998061437,25 -19817,1515998130832,26 -19818,1515998197081,26 -19819,1515998242976,26 -19820,1515998278691,25 -19821,1515998337805,27 -19822,1515998401140,27 -19823,1515998584675,29 -19824,1515998803544,28 -19825,1515998874775,27 -19826,1515998954405,27 -19827,1515999097101,27 -19828,1515999228157,27 -19829,1515999320930,26 -19830,1515999381250,25 -19831,1515999488159,25 -19832,1515999673578,24 -19833,1515999927150,26 -19834,1516000137113,25 -19835,1516000229297,24 -19836,1516000285348,24 -19837,1516000356106,24 -19838,1516000425681,24 -19839,1516000580090,25 -19840,1516000783374,24 -19841,1516000897762,24 -19842,1516000945298,23 -19843,1516001186158,23 -19844,1516001415888,22 -19845,1516001434936,21 -19846,1516001453952,24 -19847,1516001544376,25 -19848,1516001629135,26 -19849,1516001661363,25 -19850,1516001745175,25 -19851,1516001875525,25 -19852,1516001995155,24 -19853,1516002088776,24 -19854,1516002144708,24 -19855,1516002176905,23 -19856,1516002292750,24 -19857,1516002338274,23 -19858,1516002367022,24 -19859,1516002428644,25 -19860,1516002528691,25 -19861,1516002642212,25 -19862,1516002694461,24 -19863,1516002710306,23 -19864,1516002803018,25 -19865,1516002929443,25 -19866,1516003021110,24 -19867,1516003114816,24 -19868,1516003174044,23 -19869,1516003189823,24 -19870,1516003248959,26 -19871,1516003274261,26 -19872,1516003433962,29 -19873,1516003592219,28 -19874,1516003624227,27 -19875,1516003686820,27 -19876,1516003783041,28 -19877,1516003869695,27 -19878,1516003908880,26 -19879,1516003993892,27 -19880,1516004001852,26 -19881,1516004010521,33 -19882,1516004090062,41 -19883,1516004186470,41 -19884,1516004442059,39 -19885,1516004779903,39 -19886,1516004926003,39 -19887,1516005179531,38 -19888,1516005411723,37 -19889,1516005424485,37 -19890,1516005513950,42 -19891,1516005600018,42 -19892,1516005642559,42 -19893,1516005775615,43 -19894,1516005914654,43 -19895,1516006045959,43 -19896,1516006243637,42 -19897,1516006390911,41 -19898,1516006496929,40 -19899,1516006904852,39 -19900,1516007482181,38 -19901,1516007699455,36 -19902,1516007736469,35 -19903,1516007819699,37 -19904,1516007834468,37 -19905,1516007882476,43 -19906,1516007977561,43 -19907,1516008014500,44 -19908,1516008026604,45 -19909,1516008036062,52 -19910,1516008133086,65 -19911,1516008158648,64 -19912,1516008176164,70 -19913,1516008270118,76 -19914,1516008336860,77 -19915,1516008349165,77 -19916,1516008407967,91 -19917,1516008419797,93 -19918,1516008826341,109 -19919,1516008860056,107 -19920,1516008919723,112 -19921,1516008981663,115 -19922,1516009018567,117 -19923,1516009084408,122 -19924,1516009369302,124 -19925,1516009559141,122 -19926,1516009622341,119 -19927,1516009645623,121 -19928,1516009710030,131 -19929,1516009744002,133 -19930,1516009882409,139 -19931,1516009902924,138 -19932,1516010423790,150 -19933,1516010707692,147 -19934,1516011168782,144 -19935,1516011411733,142 -19936,1516011966541,139 -19937,1516012517111,136 -19938,1516012961019,133 -19939,1516013061559,130 -19940,1516013521641,129 -19941,1516014090570,126 -19942,1516200834598,123 -19943,1516200904328,120 -19944,1516201049783,119 -19945,1516201105151,118 -19946,1516201231809,120 -19947,1516201275152,119 -19948,1516201325844,122 -19949,1516201579927,124 -19950,1516201590747,121 -19951,1516201648346,144 -19952,1516201692677,146 -19953,1516202083936,149 -19954,1516202227186,145 -19955,1516202424599,143 -19956,1516202559782,141 -19957,1516202759780,138 -19958,1516202770724,136 -19959,1516203291946,162 -19960,1516203535584,157 -19961,1516203586059,155 -19962,1516204129484,156 -19963,1516204441298,153 -19964,1516204712788,150 -19965,1516204984244,146 -19966,1516205149630,141 -19967,1516205205005,138 -19968,1516205267672,139 -19969,1516205439552,140 -19970,1516205458162,138 -19971,1516205738749,151 -19972,1516206133755,147 -19973,1516206312203,142 -19974,1516206375017,138 -19975,1516206607750,139 -19976,1516206901997,134 -19977,1516207346206,130 -19978,1516207498289,125 -19979,1516207750491,122 -19980,1516207880469,117 -19981,1516208038928,118 -19982,1516208109220,119 -19983,1516208372325,118 -19984,1516208600659,113 -19985,1516208660937,109 -19986,1516208679097,107 -19987,1516208875412,115 -19988,1516208913566,111 -19989,1516209060525,112 -19990,1516209086046,111 -19991,1516209217819,116 -19992,1516209290480,113 -19993,1516209508277,111 -19994,1516209711378,106 -19995,1516210373766,101 -19996,1516210441355,96 -19997,1516210575619,93 -19998,1516210730918,88 -19999,1516210790930,84 -20000,1516210871044,81 -20001,1516210936246,78 -20002,1516210971857,74 -20003,1516211275824,73 -20004,1516211552360,68 -20005,1516211563326,65 -20006,1516211594256,74 -20007,1516211597810,74 -20008,1516211690027,119 -20009,1516211787445,118 -20010,1516211827869,121 -20011,1516211841323,121 -20012,1516211859696,139 -20013,1516211946529,155 -20014,1516212088040,153 -20015,1516212237205,149 -20016,1516212524421,151 -20017,1516212707897,147 -20018,1516212800589,150 -20019,1516212942160,148 -20020,1516212975219,147 -20021,1516213057705,153 -20022,1516213151938,152 -20023,1516213182928,152 -20024,1516213288032,160 -20025,1516213427057,156 -20026,1516213433345,153 -20027,1516213550325,206 -20028,1516214407101,209 -20029,1516215301471,203 -20030,1516215514963,201 -20031,1516215568257,196 -20032,1516215742002,205 -20033,1516215792222,201 -20034,1516216766545,204 -20035,1516216972180,196 -20036,1516217349010,192 -20037,1516217630961,185 -20038,1516217727735,178 -20039,1516218910432,175 -20040,1516219311981,169 -20041,1516219471509,163 -20042,1516219507733,158 -20043,1516219584813,160 -20044,1516219796090,159 -20045,1516220134530,154 -20046,1516220231919,149 -20047,1516220272342,146 -20048,1516220650444,150 -20049,1516220910978,145 -20050,1516221134577,139 -20051,1516221229439,147 -20052,1516221233001,145 -20053,1516221492918,240 -20054,1516222338429,234 -20055,1516222349708,227 -20056,1516223024843,266 -20057,1516223119477,259 -20058,1516223295208,257 -20059,1516223719741,266 -20060,1516223993575,258 -20061,1516224120216,252 -20062,1516224136245,251 -20063,1516224302148,280 -20064,1516224458514,274 -20065,1516224772606,269 -20066,1516225048426,262 -20067,1516225392809,255 -20068,1516225487339,250 -20069,1516226473988,249 -20070,1516226883479,240 -20071,1516226924434,242 -20072,1516226992022,246 -20073,1516227116287,246 -20074,1516227299553,241 -20075,1516227325466,237 -20076,1516227461431,250 -20077,1516228266937,244 -20078,1516228423856,235 -20079,1516229346289,229 -20080,1516229509606,220 -20081,1516229609131,215 -20082,1516229780540,209 -20083,1516229829363,204 -20084,1516230219714,204 -20085,1516230295660,196 -20086,1516230942104,193 -20087,1516230979822,191 -20088,1516231220205,193 -20089,1516231760559,188 -20090,1516231985938,179 -20091,1516232078117,176 -20092,1516232696256,170 -20093,1516232717251,164 -20094,1516232743006,172 -20095,1516232898968,178 -20096,1516232993847,171 -20097,1516233145017,166 -20098,1516233418962,158 -20099,1516233989397,150 -20100,1516234127223,141 -20101,1516234300225,134 -20102,1516234705531,127 -20103,1516234798033,119 -20104,1516234945937,111 -20105,1516234959275,102 -20106,1516235386520,118 -20107,1516235664241,111 -20108,1516235766827,126 -20109,1516235842439,120 -20110,1516236560729,115 -20111,1516236738502,110 -20112,1516236754377,112 -20113,1516237225221,129 -20114,1516237236261,122 -20115,1516237405012,140 -20116,1516237680667,133 -20117,1516237799847,125 -20118,1516237857768,119 -20119,1516238374762,116 -20120,1516238646378,108 -20121,1516238718948,104 -20122,1516238759563,100 -20123,1516239346179,98 -20124,1516239465334,95 -20125,1516239902359,88 -20126,1516240017119,80 -20127,1516240124605,103 -20128,1516240152889,99 -20129,1516240314300,98 -20130,1516240384367,91 -20131,1516240501510,87 -20132,1516240576784,84 -20133,1516240585437,80 -20134,1516240943693,98 -20135,1516241175973,90 -20136,1516241432589,83 -20137,1516241513086,76 -20138,1516241811349,70 -20139,1516241965045,64 -20140,1516242015575,56 -20141,1516242058411,50 -20142,1516242104076,46 -20143,1516242120210,45 -20144,1516242281627,45 -20145,1516242309785,38 -20146,1516242392435,32 -20147,1516242425720,27 -20148,1516242434319,24 -20149,1516242457633,23 -20150,1516242468583,17 -20151,1516242486752,13 -20152,1516242574283,7 -20153,1516242577794,49 -20154,1516242618624,76 -20155,1516242747762,74 -20156,1516242808059,92 -20157,1516242878363,89 -20158,1516242881908,88 -20159,1516242944838,143 -20160,1516242973096,141 -20161,1516243139579,146 -20162,1516243970251,142 -20163,1516244006358,154 -20164,1516244458240,159 -20165,1516244533182,153 -20166,1516244662438,152 -20167,1516244774981,148 -20168,1516244924777,144 -20169,1516245027182,142 -20170,1516245257211,139 -20171,1516245331905,133 -20172,1516245571239,137 -20173,1516245771034,135 -20174,1516245866149,132 -20175,1516245968538,129 -20176,1516246119657,136 -20177,1516246248983,134 -20178,1516246547277,130 -20179,1516246679215,125 -20180,1516246719536,121 -20181,1516246996838,122 -20182,1516247136225,119 -20183,1516247142203,116 -20184,1516247678685,160 -20185,1516247783331,154 -20186,1516247840813,153 -20187,1516248619902,152 -20188,1516248680252,152 -20189,1516248812241,151 -20190,1516249041068,147 -20191,1516249323557,142 -20192,1516249789225,138 -20193,1516249889434,132 -20194,1516250086822,137 -20195,1516250181521,139 -20196,1516250648217,137 -20197,1516250947339,133 -20198,1516250982768,128 -20199,1516251045570,131 -20200,1516251063907,129 -20201,1516251109643,140 -20202,1516251226467,141 -20203,1516251306784,136 -20204,1516251715931,135 -20205,1516251778807,129 -20206,1516252288991,136 -20207,1516252305256,129 -20208,1516252882824,142 -20209,1516253107549,136 -20210,1516253335474,133 -20211,1516253351119,126 -20212,1516253510121,139 -20213,1516254006065,142 -20214,1516254073539,136 -20215,1516254205336,147 -20216,1516254550647,143 -20217,1516254594745,138 -20218,1516255058837,139 -20219,1516255190511,135 -20220,1516255309531,131 -20221,1516255486731,126 -20222,1516255522437,122 -20223,1516255604498,127 -20224,1516255637688,122 -20225,1516255935545,126 -20226,1516255983372,119 -20227,1516256107950,118 -20228,1516256146305,115 -20229,1516256172182,118 -20230,1516256276646,123 -20231,1516256312401,119 -20232,1516256394933,120 -20233,1516256450477,118 -20234,1516256507659,126 -20235,1516256858581,124 -20236,1516256899501,118 -20237,1516256927554,118 -20238,1516257002166,121 -20239,1516257663039,118 -20240,1516257673015,111 -20241,1516257681609,131 -20242,1516257755335,161 -20243,1516257903072,159 -20244,1516258059454,157 -20245,1516258112484,150 -20246,1516258411801,150 -20247,1516258561046,143 -20248,1516258725582,137 -20249,1516258940733,134 -20250,1516258973958,128 -20251,1516259103702,131 -20252,1516259176186,125 -20253,1516259528432,121 -20254,1516259618300,130 -20255,1516259651234,127 -20256,1516259749080,128 -20257,1516259792624,125 -20258,1516260391213,126 -20259,1516260613752,148 -20260,1516260626488,144 -20261,1516260731517,171 -20262,1516261159953,168 -20263,1516261230230,161 -20264,1516261290812,164 -20265,1516261523349,163 -20266,1516262028319,160 -20267,1516262034505,154 -20268,1516262053333,208 -20269,1516262890494,227 -20270,1516263478345,220 -20271,1516263521382,212 -20272,1516263589158,218 -20273,1516264788193,218 -20274,1516264902650,209 -20275,1516264932967,206 -20276,1516265013210,215 -20277,1516265098370,213 -20278,1516265128973,211 -20279,1516265299742,219 -20280,1516265571030,214 -20281,1516266059824,209 -20282,1516266112776,201 -20283,1516266448775,201 -20284,1516266651822,218 -20285,1516266655576,211 -20286,1516266827867,339 -20287,1516266924679,336 -20288,1516267555490,333 -20289,1516267912003,327 -20290,1516268007144,320 -20291,1516268134226,317 -20292,1516268331057,312 -20293,1516268970784,305 -20294,1516270283459,297 -20295,1516270517883,287 -20296,1516270578598,280 -20297,1516270631885,281 -20298,1516270821879,283 -20299,1516271132448,279 -20300,1516272031642,272 -20301,1516272450160,270 -20302,1516272753906,264 -20303,1516272873168,257 -20304,1516273476435,253 -20305,1516273644455,243 -20306,1516273757155,238 -20307,1516274146766,233 -20308,1516274204684,233 -20309,1516274411194,232 -20310,1516274951098,224 -20311,1516275090543,215 -20312,1516275252397,217 -20313,1516275512819,211 -20314,1516275531337,202 -20315,1516275566819,220 -20316,1516275982265,225 -20317,1516276580857,215 -20318,1516276592058,209 -20319,1516276657745,243 -20320,1516277157262,241 -20321,1516277886828,232 -20322,1516277892956,221 -20323,1516278824302,300 -20324,1516278866997,289 -20325,1516279019419,297 -20326,1516279197118,289 -20327,1516279267952,283 -20328,1516279397962,280 -20329,1516280035298,276 -20330,1516280654620,268 -20331,1516280802226,258 -20332,1516281051269,253 -20333,1516281109087,245 -20334,1516281363181,244 -20335,1516281462978,236 -20336,1516282259131,229 -20337,1516282347719,220 -20338,1516282353647,218 -20339,1516282384897,296 -20340,1516282539560,304 -20341,1516283371496,308 -20342,1516284218693,313 -20343,1516284658460,302 -20344,1516284945329,292 -20345,1516285837900,282 -20346,1516286181703,273 -20347,1516286351319,262 -20348,1516286627373,253 -20349,1516286803509,242 -20350,1516286854794,233 -20351,1516286860929,235 -20352,1516286874605,314 -20353,1516287880696,357 -20354,1516288082202,341 -20355,1516288227438,332 -20356,1516289216078,326 -20357,1516289356521,313 -20358,1516289762223,306 -20359,1516289822202,293 -20360,1516290172842,289 -20361,1516290472732,289 -20362,1516290893692,278 -20363,1516291180389,264 -20364,1516291698229,254 -20365,1516291704476,243 -20366,1516291858093,323 -20367,1516291889056,311 -20368,1516291905209,349 -20369,1516292102762,398 -20370,1516295012917,387 -20371,1516295985068,370 -20372,1516296942668,361 -20373,1516296968071,349 -20374,1516298092474,366 -20375,1516298348196,352 -20376,1516298840063,347 -20377,1516300771374,335 -20378,1516300978214,322 -20379,1516300999054,317 -20380,1516302606845,339 -20381,1516302944804,324 -20382,1516303042190,310 -20383,1516303428027,305 -20384,1516304445668,291 -20385,1516304797203,277 -20386,1516305139484,331 -20387,1516305293222,321 -20388,1516305450987,315 -20389,1516305806051,306 -20390,1516306020444,294 -20391,1516306249018,287 -20392,1516307724948,279 -20393,1516308219075,267 -20394,1516308532732,254 -20395,1516308699636,242 -20396,1516308939441,232 -20397,1516309072431,225 -20398,1516309223537,222 -20399,1516309528204,212 -20400,1516309787577,201 -20401,1516309938201,189 -20402,1516309972569,178 -20403,1516310342013,177 -20404,1516310372915,166 -20405,1516310450399,165 -20406,1516310515003,158 -20407,1516310538092,151 -20408,1516310610847,153 -20409,1516310696954,148 -20410,1516310987860,139 -20411,1516311023967,126 -20412,1516311085415,121 -20413,1516311106626,113 -20414,1516311216587,111 -20415,1516311643382,112 -20416,1516311664680,105 -20417,1516311926646,103 -20418,1516311985762,90 -20419,1516312028774,103 -20420,1516312262507,98 -20421,1516312401937,86 -20422,1516312699683,74 -20423,1516312751196,105 -20424,1516312874223,97 -20425,1516312930095,94 -20426,1516313043363,89 -20427,1516313047338,80 -20428,1516313122584,120 -20429,1516313148115,114 -20430,1516313385118,112 -20431,1516313485663,100 -20432,1516313526265,92 -20433,1516313572759,85 -20434,1516313591489,82 -20435,1516313812656,80 -20436,1516313843841,70 -20437,1516313862612,63 -20438,1516314063550,61 -20439,1516314069637,93 -20440,1516314399151,130 -20441,1516314449589,121 -20442,1516314540918,115 -20443,1516314804517,106 -20444,1516314903295,96 -20445,1516314906695,87 -20446,1516315085299,137 -20447,1516315914034,126 -20448,1516315932523,115 -20449,1516316107432,118 -20450,1516316428601,108 -20451,1516316493000,102 -20452,1516316545847,139 -20453,1516316593829,162 -20454,1516316702013,159 -20455,1516316896709,155 -20456,1516317219547,148 -20457,1516317839118,138 -20458,1516317850116,130 -20459,1516318013847,148 -20460,1516318048127,146 -20461,1516318081404,145 -20462,1516318097373,145 -20463,1516318292056,156 -20464,1516318320965,147 -20465,1516318506065,148 -20466,1516318616870,186 -20467,1516319583648,183 -20468,1516319951795,184 -20469,1516319998973,202 -20470,1516320037220,205 -20471,1516320365160,209 -20472,1516320959547,201 -20473,1516320997760,192 -20474,1516321043621,212 -20475,1516321065759,213 -20476,1516321306818,228 -20477,1516321632113,222 -20478,1516321740773,214 -20479,1516321759751,211 -20480,1516322223039,246 -20481,1516322449909,238 -20482,1516322896955,232 -20483,1516323083417,227 -20484,1516323148676,221 -20485,1516323179623,220 -20486,1516323407734,228 -20487,1516323745827,222 -20488,1516324080877,215 -20489,1516324803507,209 -20490,1516325053605,202 -20491,1516325087160,195 -20492,1516325555186,201 -20493,1516325785241,192 -20494,1516325885024,185 -20495,1516325906212,180 -20496,1516326055995,191 -20497,1516327060307,186 -20498,1516327443476,177 -20499,1516327726634,170 -20500,1516328109559,162 -20501,1516328199943,153 -20502,1516328218401,149 -20503,1516328488643,165 -20504,1516328842263,155 -20505,1516329130073,153 -20506,1516329170953,147 -20507,1516329373960,148 -20508,1516329456138,148 -20509,1516329474316,144 -20510,1516329541986,156 -20511,1516329577401,152 -20512,1516329656558,155 -20513,1516330166433,152 -20514,1516330182818,149 -20515,1516330414537,162 -20516,1516330427938,154 -20517,1516331008278,176 -20518,1516331271926,167 -20519,1516331300208,160 -20520,1516331370859,166 -20521,1516331394304,161 -20522,1516331456850,167 -20523,1516331514878,163 -20524,1516331588049,162 -20525,1516331676722,157 -20526,1516331788548,151 -20527,1516331972494,144 -20528,1516331978751,160 -20529,1516332298519,212 -20530,1516332603942,208 -20531,1516332773342,198 -20532,1516332853645,191 -20533,1516333139500,189 -20534,1516333152827,181 -20535,1516333239952,207 -20536,1516333437695,202 -20537,1516333891365,196 -20538,1516334038815,189 -20539,1516334059721,181 -20540,1516334314086,209 -20541,1516334782669,200 -20542,1516334870158,193 -20543,1516335031835,189 -20544,1516335315853,181 -20545,1516336396892,171 -20546,1516337224301,193 -20547,1516337557808,184 -20548,1516337665417,175 -20549,1516338158959,176 -20550,1516339038946,167 -20551,1516339108508,157 -20552,1516339405789,155 -20553,1516340007573,149 -20554,1516340011730,143 -20555,1516340313926,218 -20556,1516340339941,209 -20557,1516340587997,218 -20558,1516340663025,209 -20559,1516340669102,218 -20560,1516340860009,294 -20561,1516340975205,291 -20562,1516342616898,290 -20563,1516343419151,289 -20564,1516343467621,279 -20565,1516343771603,287 -20566,1516345085067,278 -20567,1516345742413,269 -20568,1516345775778,258 -20569,1516345846188,265 -20570,1516345970210,267 -20571,1516345983675,267 -20572,1516346132628,303 -20573,1516346201285,295 -20574,1516346488161,299 -20575,1516346581030,294 -20576,1516346886603,301 -20577,1516347189351,292 -20578,1516347215226,283 -20579,1516347497284,299 -20580,1516347849268,302 -20581,1516349207711,293 -20582,1516349555799,282 -20583,1516349680468,272 -20584,1516349782454,267 -20585,1516350205091,264 -20586,1516350544257,262 -20587,1516350839751,254 -20588,1516350860725,244 -20589,1516351040349,261 -20590,1516351191756,251 -20591,1516351576986,244 -20592,1516351652173,240 -20593,1516352113743,236 -20594,1516352712132,225 -20595,1516353005733,216 -20596,1516353070727,215 -20597,1516353237871,213 -20598,1516353407588,204 -20599,1516353475872,194 -20600,1516353612672,190 -20601,1516353665965,181 -20602,1516353837988,179 -20603,1516354076619,179 -20604,1516354109821,169 -20605,1516354330352,170 -20606,1516354353856,160 -20607,1516354561471,168 -20608,1516354651218,158 -20609,1516354659707,152 -20610,1516354675767,192 -20611,1516354743726,210 -20612,1516354869973,210 -20613,1516354885796,203 -20614,1516355090036,220 -20615,1516355315048,221 -20616,1516357605384,211 -20617,1516357882462,212 -20618,1516357938008,200 -20619,1516358028089,198 -20620,1516358160036,196 -20621,1516358599899,190 -20622,1516358678154,186 -20623,1516359196982,183 -20624,1516359524127,174 -20625,1516359809540,165 -20626,1516359949774,156 -20627,1516359963319,147 -20628,1516360183858,163 -20629,1516360231483,182 -20630,1516360274773,180 -20631,1516360416605,179 -20632,1516360516060,171 -20633,1516360593150,166 -20634,1516360688051,160 -20635,1516360770566,168 -20636,1516360975458,164 -20637,1516360979143,156 -20638,1516361231902,246 -20639,1516362596515,237 -20640,1516363437590,234 -20641,1516363568241,223 -20642,1516364449986,215 -20643,1516364639834,205 -20644,1516365144954,196 -20645,1516365250717,185 -20646,1516365826873,176 -20647,1516366248142,164 -20648,1516366296155,152 -20649,1516366408587,149 -20650,1516366633732,140 -20651,1516366795064,128 -20652,1516366895957,119 -20653,1516366983261,110 -20654,1516367198275,100 -20655,1516367330388,131 -20656,1516368048933,122 -20657,1516368632828,121 -20658,1516369144420,110 -20659,1516369223331,103 -20660,1516369256710,138 -20661,1516369292469,140 -20662,1516369387852,142 -20663,1516369758894,136 -20664,1516369812127,126 -20665,1516369877540,128 -20666,1516369982472,124 -20667,1516370444345,117 -20668,1516370586798,108 -20669,1516370679164,109 -20670,1516370768939,105 -20671,1516371052481,102 -20672,1516371132435,117 -20673,1516371238193,114 -20674,1516371634854,112 -20675,1516371791511,105 -20676,1516371807247,100 -20677,1516371843013,109 -20678,1516371916081,108 -20679,1516371991413,115 -20680,1516372095582,111 -20681,1516372175567,106 -20682,1516372234217,100 -20683,1516372338037,96 -20684,1516372410355,92 -20685,1516372443801,90 -20686,1516372523944,88 -20687,1516372532565,82 -20688,1516372592919,97 -20689,1516372628910,106 -20690,1516372761219,106 -20691,1516372896213,100 -20692,1516372924173,94 -20693,1516372970509,97 -20694,1516373099691,93 -20695,1516373224459,86 -20696,1516373363410,80 -20697,1516373416332,76 -20698,1516373501487,73 -20699,1516373648385,67 -20700,1516374157287,62 -20701,1516374187716,56 -20702,1516374264229,55 -20703,1516374349030,49 -20704,1516374495646,43 -20705,1516374508237,41 -20706,1516374694386,41 -20707,1516374805079,41 -20708,1516374946552,34 -20709,1516375162522,29 -20710,1516375173411,43 -20711,1516375180779,59 -20712,1516375395660,75 -20713,1516375411609,70 -20714,1516375541452,88 -20715,1516375907563,84 -20716,1516376007631,79 -20717,1516376020821,74 -20718,1516376086231,81 -20719,1516376102278,81 -20720,1516376209768,88 -20721,1516376312580,85 -20722,1516376572631,80 -20723,1516376630232,75 -20724,1516376937244,72 -20725,1516377069630,65 -20726,1516377098057,60 -20727,1516377136338,58 -20728,1516377238978,69 -20729,1516377334019,63 -20730,1516377346745,63 -20731,1516377353676,73 -20732,1516377444816,93 -20733,1516377599022,89 -20734,1516377656981,87 -20735,1516377809256,85 -20736,1516377963584,82 -20737,1516378102311,76 -20738,1516378258162,123 -20739,1516378375520,120 -20740,1516378465990,118 -20741,1516378543761,115 -20742,1516378663818,115 -20743,1516378697361,112 -20744,1516378856039,115 -20745,1516378862058,112 -20746,1516378918607,153 -20747,1516378967217,153 -20748,1516379000122,155 -20749,1516379698593,163 -20750,1516379724234,158 -20751,1516379851243,168 -20752,1516379998542,165 -20753,1516380088252,162 -20754,1516380353810,161 -20755,1516380389729,156 -20756,1516380474615,161 -20757,1516380867926,158 -20758,1516381106181,152 -20759,1516381460546,147 -20760,1516381958452,143 -20761,1516382255706,142 -20762,1516382625781,140 -20763,1516382814617,136 -20764,1517433080252,131 -20765,1517433576736,127 -20766,1517434075014,124 -20767,1517434458470,119 -20768,1517434985610,114 -20769,1517435345939,108 -20770,1517435548379,103 -20771,1517435837345,100 -20772,1517436673221,94 -20773,1517437317281,90 -20774,1517437399052,85 -20775,1517438118935,82 -20776,1517438471890,76 -20777,1517439081656,78 -20778,1517439801736,76 -20779,1517439976475,72 -20780,1517440125190,69 -20781,1517440271641,65 -20782,1517440321361,62 -20783,1517440423408,60 -20784,1517440671984,57 -20785,1517440879405,54 -20786,1517440951916,51 -20787,1517441018206,48 -20788,1517441218012,56 -20789,1517441377374,53 -20790,1517441443814,52 -20791,1517441502692,50 -20792,1517441575499,47 -20793,1517441625883,47 -20794,1517441700145,47 -20795,1517442065188,44 -20796,1517442429521,40 -20797,1517442530322,35 -20798,1517442697889,33 -20799,1517442877933,29 -20800,1517443011009,25 -20801,1517443201815,21 -20802,1517443391493,18 -20803,1517443513398,14 -20804,1517443613425,10 -20805,1517443690311,5 -20806,1517443706515,5 -20807,1517443718914,1 -20808,1517443738628,1 -20809,1517443757857,1 -20810,1517443766923,1 -20811,1517443775970,1 -20812,1517443784712,1 -20813,1517443793714,1 -20814,1517443802715,1 -20815,1517443815158,1 -20816,1517443824389,1 -20817,1517443833388,1 -20818,1517443842289,1 -20819,1517443851638,1 -20820,1517443860560,1 -20821,1517443869637,1 -20822,1517443878558,1 -20823,1517443887578,1 -20824,1517443899996,1 -20825,1517443912391,1 -20826,1517443921164,1 -20827,1517443930227,1 -20828,1517443946010,1 -20829,1517443961939,1 -20830,1517443970874,1 -20831,1517443980019,1 -20832,1517443989271,1 -20833,1517443998327,1 -20834,1517444007371,1 -20835,1517444016273,1 -20836,1517444025148,1 -20837,1517444034121,1 -20838,1517444042914,1 -20839,1517444052044,1 -20840,1517444067546,1 -20841,1517444076286,1 -20842,1517444085407,1 -20843,1517444094364,1 -20844,1517444103354,1 -20845,1517444112375,1 -20846,1517444121107,1 -20847,1517444130000,1 -20848,1517444139331,1 -20849,1517444151747,1 -20850,1517444161029,1 -20851,1517444173286,1 -20852,1517444182274,1 -20853,1517444191217,1 -20854,1517444200324,1 -20855,1517444209437,1 -20856,1517444218299,1 -20857,1517444227463,1 -20858,1517444236710,1 -20859,1517444245698,1 -20860,1517444254604,1 -20861,1517444270597,1 -20862,1517444279249,1 -20863,1517444288185,1 -20864,1517444297062,1 -20865,1517444305953,1 -20866,1517444314935,1 -20867,1517444324322,1 -20868,1517444333525,1 -20869,1517444342392,1 -20870,1517444354826,1 -20871,1517444363870,1 -20872,1517444376358,1 -20873,1517444385456,1 -20874,1517444394367,1 -20875,1517444406791,1 -20876,1517444415582,1 -20877,1517444424496,1 -20878,1517444440038,1 -20879,1517444449036,1 -20880,1517444458126,1 -20881,1517444467285,1 -20882,1517444476087,1 -20883,1517444488699,1 -20884,1517444501473,1 -20885,1517444510188,1 -20886,1517444522328,1 -20887,1517444531163,1 -20888,1517444543512,1 -20889,1517444552463,1 -20890,1517444561338,1 -20891,1517444570452,2 -20892,1517444579932,3 -20893,1517444592257,4 -20894,1517444601015,5 -20895,1517444617030,7 -20896,1517444673353,8 -20897,1517444723211,8 -20898,1517444790235,9 -20899,1517444812857,8 -20900,1517444863032,9 -20901,1517444905632,9 -20902,1517444938512,10 -20903,1517444974525,10 -20904,1517445034634,10 -20905,1517445084911,10 -20906,1517445100711,10 -20907,1517445139947,12 -20908,1517445206417,12 -20909,1517445263230,13 -20910,1517445292668,13 -20911,1517445305241,13 -20912,1517445317561,15 -20913,1517445329709,18 -20914,1517445345535,21 -20915,1517445418794,23 -20916,1517445537290,24 -20917,1517445718816,24 -20918,1517445890479,24 -20919,1517445960549,23 -20920,1517446023514,24 -20921,1517446076742,24 -20922,1517446102821,25 -20923,1517446199519,26 -20924,1517446290041,27 -20925,1517446400311,26 -20926,1517446487063,26 -20927,1517446526901,26 -20928,1517446579871,27 -20929,1517446666763,28 -20930,1517446767054,28 -20931,1517446904657,28 -20932,1517447027655,28 -20933,1517447080351,28 -20934,1517447204043,27 -20935,1517447334799,28 -20936,1517447404068,27 -20937,1517447477034,27 -20938,1517447536697,28 -20939,1517447599514,28 -20940,1517447706399,28 -20941,1517448115940,28 -20942,1517448459491,28 -20943,1517448621024,27 -20944,1517448697559,27 -20945,1517448709520,27 -20946,1517448826583,32 -20947,1517448957975,31 -20948,1517449062541,31 -20949,1517449204754,31 -20950,1517449387381,31 -20951,1517449612535,30 -20952,1517449760313,30 -20953,1517449809732,29 -20954,1517449913327,29 -20955,1517449977221,30 -20956,1517450131380,30 -20957,1517450167051,29 -20958,1517450185958,30 -20959,1517450231870,33 -20960,1517450274255,34 -20961,1517450330959,34 -20962,1517450421381,35 -20963,1517450497687,34 -20964,1517450679125,35 -20965,1517450854714,34 -20966,1517450891230,34 -20967,1517450940970,35 -20968,1517451170645,35 -20969,1517451572901,34 -20970,1517451816875,33 -20971,1517451901011,33 -20972,1517452177316,32 -20973,1517452447900,31 -20974,1517452681626,30 -20975,1517452926605,29 -20976,1517453007998,29 -20977,1517453080480,29 -20978,1517453227909,28 -20979,1517453339880,27 -20980,1517453418936,26 -20981,1517453563524,26 -20982,1517453731577,26 -20983,1517453927012,25 -20984,1517454054405,23 -20985,1517454089979,23 -20986,1517454257906,23 -20987,1517454475998,22 -20988,1517454560898,22 -20989,1517454592868,20 -20990,1517454625175,20 -20991,1517454640790,21 -20992,1517454693129,23 -20993,1517454748236,24 -20994,1517454763503,23 -20995,1517454835679,26 -20996,1517454924250,26 -20997,1517455073093,25 -20998,1517455308857,25 -20999,1517455622954,23 -21000,1517455787050,23 -21001,1517455812512,21 -21002,1517455854622,22 -21003,1517455909569,22 -21004,1517456064945,22 -21005,1517456209915,21 -21006,1517456268661,20 -21007,1517456324230,20 -21008,1517456336144,20 -21009,1517456502553,23 -21010,1517456628361,21 -21011,1517456727085,22 -21012,1517456894196,22 -21013,1517457125280,22 -21014,1517457289558,22 -21015,1517457351043,23 -21016,1517457425932,22 -21017,1517457494552,22 -21018,1517457526868,22 -21019,1517457638976,23 -21020,1517457767149,22 -21021,1517457846471,21 -21022,1517457912031,21 -21023,1517458036459,22 -21024,1517458172033,21 -21025,1517458194343,20 -21026,1517458289988,21 -21027,1517458378342,20 -21028,1517458463675,20 -21029,1517458532494,20 -21030,1517458594980,20 -21031,1517458640077,20 -21032,1517458655389,20 -21033,1517458667604,21 -21034,1517458749870,25 -21035,1517458825025,24 -21036,1517458894996,24 -21037,1517458957463,24 -21038,1517459112842,24 -21039,1517459241066,24 -21040,1517459279872,23 -21041,1517459328083,23 -21042,1517459360122,23 -21043,1517459448592,23 -21044,1517459537124,23 -21045,1517459549035,22 -21046,1517459604054,28 -21047,1517459672344,28 -21048,1517459728437,28 -21049,1517459940742,28 -21050,1517460151940,27 -21051,1517460304122,26 -21052,1517460489058,25 -21053,1517460551125,25 -21054,1517460593686,24 -21055,1517460688958,24 -21056,1517460774594,24 -21057,1517460833354,24 -21058,1517461030766,23 -21059,1517461235708,25 -21060,1517461307311,25 -21061,1517461394115,25 -21062,1517461459589,26 -21063,1517461488273,25 -21064,1517461520508,27 -21065,1517461579683,27 -21066,1517461635170,27 -21067,1517461699871,28 -21068,1517461777700,28 -21069,1517461898619,28 -21070,1517462024208,27 -21071,1517462174587,26 -21072,1517462428903,26 -21073,1517462576519,25 -21074,1517462704392,24 -21075,1517462845900,23 -21076,1517462951430,22 -21077,1517463039755,22 -21078,1517463115069,22 -21079,1517463236700,21 -21080,1517463311735,21 -21081,1517463380511,20 -21082,1517463442582,19 -21083,1517463507344,19 -21084,1517463582151,18 -21085,1517463640666,18 -21086,1517463708906,18 -21087,1517463747833,18 -21088,1517463774212,17 -21089,1517463800269,17 -21090,1517463855243,18 -21091,1517463903636,19 -21092,1517464015176,20 -21093,1517464136944,20 -21094,1517464169306,19 -21095,1517464197641,21 -21096,1517464213141,22 -21097,1517464228412,24 -21098,1517464336138,27 -21099,1517464480291,26 -21100,1517464558534,26 -21101,1517464594092,25 -21102,1517464612860,26 -21103,1517464652046,28 -21104,1517464876289,29 -21105,1517465269113,28 -21106,1517465490164,27 -21107,1517465684872,26 -21108,1517465875252,25 -21109,1517465904307,26 -21110,1517465959397,28 -21111,1517466054248,27 -21112,1517466260935,27 -21113,1517466490593,26 -21114,1517466585173,24 -21115,1517466620152,24 -21116,1517466718583,24 -21117,1517466846547,24 -21118,1517466918726,23 -21119,1517467007560,24 -21120,1517467105399,23 -21121,1517467209927,22 -21122,1517467324986,21 -21123,1517467413331,21 -21124,1517467455176,20 -21125,1517467589935,20 -21126,1517467725099,20 -21127,1517467859968,20 -21128,1517468014169,19 -21129,1517468062909,17 -21130,1517468071767,17 -21131,1517468156238,21 -21132,1517468211688,21 -21133,1517468251084,21 -21134,1517468322737,24 -21135,1517468414668,23 -21136,1517468608916,23 -21137,1517468804160,22 -21138,1517468859020,22 -21139,1517468897402,21 -21140,1517468922514,21 -21141,1517468991347,22 -21142,1517469124665,22 -21143,1517469240707,22 -21144,1517469380375,22 -21145,1517469517457,21 -21146,1517469573923,22 -21147,1517469648787,22 -21148,1517469723781,22 -21149,1517469813227,22 -21150,1517469979261,22 -21151,1517470129325,21 -21152,1517470245037,20 -21153,1517470350897,20 -21154,1517470398040,19 -21155,1517470414164,19 -21156,1517470459628,21 -21157,1517470509545,21 -21158,1517470549966,21 -21159,1517470568786,21 -21160,1517470593399,23 -21161,1517470618774,25 -21162,1517481727679,26 -21163,1517481809129,25 -21164,1517481858798,25 -21165,1517481931700,26 -21166,1517481994445,26 -21167,1517482026091,26 -21168,1517482271372,27 -21169,1517482375304,27 -21170,1517482406237,26 -21171,1517482532414,27 -21172,1517482772210,26 -21173,1517482879181,25 -21174,1517482958152,24 -21175,1517482990638,24 -21176,1517483012733,24 -21177,1517483187452,26 -21178,1517483363191,25 -21179,1517483398434,25 -21180,1517483467402,25 -21181,1517483522531,24 -21182,1517483571813,24 -21183,1517483627261,24 -21184,1517483720091,24 -21185,1517483801699,23 -21186,1517483852219,23 -21187,1517483903533,23 -21188,1517483921759,23 -21189,1517483993308,26 -21190,1517484045192,26 -21191,1517484062288,25 -21192,1517484079397,28 -21193,1517484124908,31 -21194,1517484208092,31 -21195,1517484329432,30 -21196,1517484583965,31 -21197,1517484816442,31 -21198,1517484864727,31 -21199,1517484916199,32 -21200,1517484963984,32 -21201,1517485012341,32 -21202,1517485063468,34 -21203,1517485122141,35 -21204,1517485304749,36 -21205,1517485467588,35 -21206,1517485548340,34 -21207,1517485632315,34 -21208,1517485678117,33 -21209,1517485745114,34 -21210,1517485827349,34 -21211,1517485869385,35 -21212,1517486031495,35 -21213,1517486166559,34 -21214,1517486248152,34 -21215,1517486324436,34 -21216,1517486585473,34 -21217,1517486836999,32 -21218,1517486874757,32 -21219,1517486939789,32 -21220,1517487000672,33 -21221,1517487061575,32 -21222,1517487212624,32 -21223,1517487334569,31 -21224,1517487353693,31 -21225,1517487461722,33 -21226,1517487660010,33 -21227,1517488000611,31 -21228,1517488416467,30 -21229,1517488587929,29 -21230,1517488730358,28 -21231,1517488812869,29 -21232,1517488856395,29 -21233,1517488906062,29 -21234,1517488983783,30 -21235,1517489198740,29 -21236,1517489203367,29 -21237,1517489312770,42 -21238,1517489442398,41 -21239,1517489577512,40 -21240,1517489644846,40 -21241,1517489745909,40 -21242,1517490162979,40 -21243,1517490612988,38 -21244,1517490781816,38 -21245,1517490806258,37 -21246,1517490837131,38 -21247,1517491003000,39 -21248,1517491149619,38 -21249,1517491186760,38 -21250,1517491314333,39 -21251,1517491668003,37 -21252,1517491996486,36 -21253,1517492058632,34 -21254,1517492266287,34 -21255,1517492371619,33 -21256,1517492619726,34 -21257,1517492956481,32 -21258,1517493126041,31 -21259,1517493194241,31 -21260,1517493266746,31 -21261,1517493397656,31 -21262,1517493468652,31 -21263,1517493612848,31 -21264,1517493733827,29 -21265,1517493851344,28 -21266,1517493935936,28 -21267,1517494103614,27 -21268,1517494235058,27 -21269,1517494311630,26 -21270,1517494427161,25 -21271,1517494547602,25 -21272,1517494608015,24 -21273,1517494675058,23 -21274,1517494712816,23 -21275,1517494923444,23 -21276,1517495043958,22 -21277,1517495231333,22 -21278,1517495297824,21 -21279,1517495331692,20 -21280,1517495410934,20 -21281,1517495473676,20 -21282,1517495492388,19 -21283,1517495586930,21 -21284,1517495685713,20 -21285,1517495706931,19 -21286,1517495716063,20 -21287,1517495775620,24 -21288,1517495851924,23 -21289,1517495926333,24 -21290,1517495988575,23 -21291,1517495999230,23 -21292,1517496057888,28 -21293,1517496122894,29 -21294,1517496176793,30 -21295,1517496306396,30 -21296,1517496413232,29 -21297,1517496436672,28 -21298,1517496517630,30 -21299,1517496593347,29 -21300,1517496648564,29 -21301,1517496680512,30 -21302,1517496721393,30 -21303,1517496853168,31 -21304,1517497022278,31 -21305,1517497137860,30 -21306,1517497197479,29 -21307,1517497307027,29 -21308,1517497408874,28 -21309,1517497488510,28 -21310,1517497617794,28 -21311,1517497784448,27 -21312,1517497879680,27 -21313,1517497913135,26 -21314,1517497959582,26 -21315,1517498058594,26 -21316,1517498119008,26 -21317,1517498131955,25 -21318,1517498378232,28 -21319,1517498511303,27 -21320,1517498621718,27 -21321,1517498678546,26 -21322,1517498735885,26 -21323,1517498836123,26 -21324,1517498926681,25 -21325,1517498971503,26 -21326,1517499153746,26 -21327,1517499281053,25 -21328,1517499327859,24 -21329,1517499365043,23 -21330,1517499426343,23 -21331,1517499480105,22 -21332,1517499713643,22 -21333,1517499931193,21 -21334,1517499939291,20 -21335,1517499950643,25 -21336,1517500014514,29 -21337,1517500074434,36 -21338,1517500152533,36 -21339,1517500200225,36 -21340,1517500231674,36 -21341,1517500378921,38 -21342,1517500737639,37 -21343,1517501005432,36 -21344,1517501329347,35 -21345,1517501686975,33 -21346,1517501760328,34 -21347,1517501875135,35 -21348,1517501966218,34 -21349,1517501984443,34 -21350,1517502061480,37 -21351,1517502134129,38 -21352,1517511077024,37 -21353,1517511145894,36 -21354,1517511225250,35 -21355,1517511413461,35 -21356,1517511548315,34 -21357,1517512379756,34 -21358,1517512479264,33 -21359,1517512618100,32 -21360,1517512836313,31 -21361,1517512984867,30 -21362,1517513018871,29 -21363,1517513129034,30 -21364,1517513261931,29 -21365,1517513305286,28 -21366,1517513333270,29 -21367,1517513458899,30 -21368,1517513730288,29 -21369,1517513894725,27 -21370,1517513988893,26 -21371,1517514003718,26 -21372,1517514066174,28 -21373,1517514134585,28 -21374,1517514158811,28 -21375,1517514208513,29 -21376,1517514290289,29 -21377,1517514374893,28 -21378,1517514601592,27 -21379,1517514800756,26 -21380,1517514856979,25 -21381,1517514903497,25 -21382,1517515010356,24 -21383,1517515101117,25 -21384,1517515150482,23 -21385,1517515269379,24 -21386,1517515366618,23 -21387,1517515461011,24 -21388,1517515571517,23 -21389,1517515614858,23 -21390,1517515635735,22 -21391,1517515659835,24 -21392,1517515705829,27 -21393,1517515816125,28 -21394,1517515926298,27 -21395,1517515960366,27 -21396,1517516013677,27 -21397,1517516100864,27 -21398,1517516233141,27 -21399,1517516355465,26 -21400,1517516427809,26 -21401,1517516575739,26 -21402,1517516701709,26 -21403,1517516726088,25 -21404,1517516776051,26 -21405,1517516857739,26 -21406,1517516914071,25 -21407,1517516932078,26 -21408,1517516950039,27 -21409,1517517171205,30 -21410,1517517398684,29 -21411,1517517803961,28 -21412,1517518212875,26 -21413,1517518237022,25 -21414,1517518355926,27 -21415,1517518434197,27 -21416,1517518589431,26 -21417,1517518847974,25 -21418,1517519005699,26 -21419,1517519033032,24 -21420,1517519070235,25 -21421,1517519166726,26 -21422,1517519238039,25 -21423,1517519253008,25 -21424,1517519270678,28 -21425,1517519314816,30 -21426,1517519339508,30 -21427,1517519385933,31 -21428,1517519454378,32 -21429,1517519529273,31 -21430,1517519581555,32 -21431,1517519680457,31 -21432,1517519830357,31 -21433,1517519954931,29 -21434,1517520026456,28 -21435,1517520056825,30 -21436,1517520104487,34 -21437,1517520109240,34 -21438,1517520176939,51 -21439,1517520285977,50 -21440,1517520372854,51 -21441,1517520432428,52 -21442,1517520481483,52 -21443,1517520540613,52 -21444,1517520624933,52 -21445,1517520755528,52 -21446,1517521154652,52 -21447,1517521458003,50 -21448,1517521504606,49 -21449,1517521682331,50 -21450,1517521860732,51 -21451,1517521903561,50 -21452,1517522158033,51 -21453,1517522226382,50 -21454,1517522278367,50 -21455,1517522506550,51 -21456,1517522899667,49 -21457,1517523187259,48 -21458,1517523336832,46 -21459,1517523445945,46 -21460,1517523551645,45 -21461,1517523587970,43 -21462,1517523615245,45 -21463,1517523649093,48 -21464,1517523761519,50 -21465,1517523988469,48 -21466,1517524124005,47 -21467,1517524191788,47 -21468,1517524418708,47 -21469,1517524619939,46 -21470,1517524691753,44 -21471,1517524728385,44 -21472,1517524793186,47 -21473,1517525097990,47 -21474,1517525428317,46 -21475,1517525559742,45 -21476,1517525631629,44 -21477,1517525662430,44 -21478,1517525856721,46 -21479,1517526116708,44 -21480,1517526191328,42 -21481,1517526413574,42 -21482,1517526589583,41 -21483,1517526948034,39 -21484,1517527314568,38 -21485,1517527345451,36 -21486,1517527436015,37 -21487,1517527554727,37 -21488,1517527645447,35 -21489,1517527794082,34 -21490,1517527891039,34 -21491,1517527953261,33 -21492,1517528115990,34 -21493,1517528240906,32 -21494,1517528252464,32 -21495,1517528323723,36 -21496,1517528559959,36 -21497,1517528741778,35 -21498,1517528766610,34 -21499,1517528799726,35 -21500,1517528845994,36 -21501,1517528895748,35 -21502,1517529018479,35 -21503,1517529185174,34 -21504,1517529272751,33 -21505,1517529303240,32 -21506,1517529334033,33 -21507,1517529513067,34 -21508,1517529704560,34 -21509,1517529756797,33 -21510,1517529797179,33 -21511,1517529878264,33 -21512,1517529969088,32 -21513,1517530018779,30 -21514,1517530074470,31 -21515,1517530158791,30 -21516,1517530287439,29 -21517,1517530397305,28 -21518,1517530471953,26 -21519,1517530546615,25 -21520,1517530649357,24 -21521,1517530743010,23 -21522,1517530811335,22 -21523,1517530857753,21 -21524,1517530885297,22 -21525,1517530915830,23 -21526,1517531032165,24 -21527,1517531177008,23 -21528,1517531238878,23 -21529,1517531269404,22 -21530,1517531335769,22 -21531,1517531398443,22 -21532,1517531416225,20 -21533,1517531472245,21 -21534,1517531528068,20 -21535,1517531618707,19 -21536,1517531709232,19 -21537,1517531762046,18 -21538,1517531833616,25 -21539,1517531876482,25 -21540,1517531894602,25 -21541,1517531937845,28 -21542,1517531990371,28 -21543,1517532017915,29 -21544,1517532035928,30 -21545,1517532139882,34 -21546,1517532312676,33 -21547,1517532425519,31 -21548,1517532525219,30 -21549,1517532741520,30 -21550,1517533009489,29 -21551,1517533129029,27 -21552,1517533204057,28 -21553,1517533285128,27 -21554,1517533337399,27 -21555,1517533396782,27 -21556,1517533456256,27 -21557,1517533568698,26 -21558,1517533650057,25 -21559,1517533705729,25 -21560,1517533783351,24 -21561,1517533861361,24 -21562,1517533932948,24 -21563,1517533991328,25 -21564,1517534082573,26 -21565,1517534148333,25 -21566,1517534302978,24 -21567,1517534494752,24 -21568,1517534551743,23 -21569,1517534569023,22 -21570,1517534628672,24 -21571,1517534697015,24 -21572,1517534743605,25 -21573,1517534805354,25 -21574,1517534886458,24 -21575,1517534964311,24 -21576,1517535107824,23 -21577,1517535220842,23 -21578,1517535260976,23 -21579,1517535317054,23 -21580,1517535341174,23 -21581,1517535444646,24 -21582,1517535522639,23 -21583,1517535578726,22 -21584,1517535635144,21 -21585,1517535687726,21 -21586,1517535852061,22 -21587,1517535993434,21 -21588,1517536027832,19 -21589,1517536045918,19 -21590,1517536149763,21 -21591,1517536281409,20 -21592,1517536353549,20 -21593,1517536432515,18 -21594,1517536524055,18 -21595,1517536564396,20 -21596,1517536626879,20 -21597,1517536679861,19 -21598,1517536713881,18 -21599,1517536744158,20 -21600,1517536781055,22 -21601,1517536811386,22 -21602,1517536848096,23 -21603,1517536920246,24 -21604,1517537036168,23 -21605,1517537120388,22 -21606,1517537154139,22 -21607,1517537266682,24 -21608,1517537350486,23 -21609,1517537444277,23 -21610,1517537499907,22 -21611,1517537530277,23 -21612,1517537605140,24 -21613,1517537707875,24 -21614,1517537776042,23 -21615,1517537794060,23 -21616,1517537957016,25 -21617,1517538114014,24 -21618,1517538131971,24 -21619,1517538168631,25 -21620,1517538259711,26 -21621,1517538325766,25 -21622,1517538460914,25 -21623,1517538605866,24 -21624,1517538655582,23 -21625,1517538717770,24 -21626,1517538913108,24 -21627,1517539060862,23 -21628,1517539088581,22 -21629,1517539157372,23 -21630,1517539239576,23 -21631,1517539308634,23 -21632,1517539446319,22 -21633,1517539558626,23 -21634,1517539576673,22 -21635,1517539585122,24 -21636,1517539631601,29 -21637,1517539725275,29 -21638,1517539831547,29 -21639,1517539893533,29 -21640,1517539980549,28 -21641,1517540061219,30 -21642,1517540161131,29 -21643,1517540298371,29 -21644,1517540385545,30 -21645,1517540409730,30 -21646,1517540427745,33 -21647,1517540477740,36 -21648,1517540590975,37 -21649,1517540712734,36 -21650,1517540850004,35 -21651,1517541067947,34 -21652,1517541196611,33 -21653,1517541300325,33 -21654,1517541441524,32 -21655,1517541539453,32 -21656,1517541556746,31 -21657,1517541612404,34 -21658,1517541718504,35 -21659,1517541789986,35 -21660,1517541810984,34 -21661,1517541870069,37 -21662,1517542046793,37 -21663,1517542258088,36 -21664,1517542380642,35 -21665,1517542449000,35 -21666,1517542492024,35 -21667,1517542513400,35 -21668,1517542622296,37 -21669,1517542744472,37 -21670,1517542775035,37 -21671,1517542986876,39 -21672,1517543204253,39 -21673,1517543288151,37 -21674,1517543448270,37 -21675,1517543666060,36 -21676,1517543807577,35 -21677,1517543891730,34 -21678,1517543995022,33 -21679,1517544034939,34 -21680,1517544059307,34 -21681,1517544099863,37 -21682,1517544187773,38 -21683,1517544354810,37 -21684,1517544566328,36 -21685,1517544748823,36 -21686,1517544839882,35 -21687,1517544899080,34 -21688,1517544964619,34 -21689,1517545084377,34 -21690,1517545184771,34 -21691,1517545348377,33 -21692,1517545518754,33 -21693,1517545575723,31 -21694,1517545631747,31 -21695,1517545659049,31 -21696,1517545733851,32 -21697,1517545888193,32 -21698,1517545995047,31 -21699,1517546022414,30 -21700,1517546053189,31 -21701,1517546153881,33 -21702,1517546473531,33 -21703,1517546746378,32 -21704,1517546833763,31 -21705,1517546911913,30 -21706,1517546955350,30 -21707,1517547115954,30 -21708,1517547330256,29 -21709,1517547417994,28 -21710,1517547454898,27 -21711,1517547529802,28 -21712,1517547627727,28 -21713,1517547696799,27 -21714,1517547739894,26 -21715,1517547903184,26 -21716,1517548054708,26 -21717,1517548107521,25 -21718,1517548216795,25 -21719,1517548298344,25 -21720,1517548322832,25 -21721,1517548413482,26 -21722,1517548555309,25 -21723,1517548693300,24 -21724,1517548837127,23 -21725,1517548971830,22 -21726,1517549087896,21 -21727,1517549206243,20 -21728,1517549321731,19 -21729,1517549377914,18 -21730,1517549437192,17 -21731,1517549505748,17 -21732,1517549548923,17 -21733,1517549596211,16 -21734,1517549632974,15 -21735,1517549654095,15 -21736,1517549703586,19 -21737,1517549791144,19 -21738,1517549901027,18 -21739,1517549966177,17 -21740,1517549977722,17 -21741,1517549992558,19 -21742,1517550004098,21 -21743,1517550018961,24 -21744,1517550030390,27 -21745,1517550064469,31 -21746,1517550123858,32 -21747,1517550198344,34 -21748,1517550297973,34 -21749,1517550410318,34 -21750,1517550545561,33 -21751,1517550724598,32 -21752,1517550876267,31 -21753,1517550953518,30 -21754,1517550984066,30 -21755,1517551068272,31 -21756,1517551277603,29 -21757,1517551438027,30 -21758,1517551513191,30 -21759,1517551594315,29 -21760,1517551665884,28 -21761,1517551797894,30 -21762,1517551954694,29 -21763,1517552070549,29 -21764,1517552136426,28 -21765,1517552163551,27 -21766,1517552190761,29 -21767,1517552246667,31 -21768,1517552309551,32 -21769,1517552358688,32 -21770,1517552494061,32 -21771,1517552776987,32 -21772,1517552984926,31 -21773,1517553062685,30 -21774,1517553159715,30 -21775,1517553243301,30 -21776,1517553326914,28 -21777,1517553360377,28 -21778,1517553388164,29 -21779,1517553512434,30 -21780,1517553766042,30 -21781,1517553996623,30 -21782,1517554093111,30 -21783,1517554167845,30 -21784,1517554230168,30 -21785,1517554292825,29 -21786,1517554399738,28 -21787,1517554561509,28 -21788,1517554715590,28 -21789,1517554796957,27 -21790,1517554848341,26 -21791,1517554951168,27 -21792,1517555036029,25 -21793,1517555085135,25 -21794,1517555103611,26 -21795,1517555123530,28 -21796,1517555216181,31 -21797,1517555293919,30 -21798,1517555419961,30 -21799,1517555522518,29 -21800,1517555615187,30 -21801,1517555700773,30 -21802,1517555781236,29 -21803,1517555918600,29 -21804,1517556028392,28 -21805,1517556146738,27 -21806,1517556303675,27 -21807,1517556418247,26 -21808,1517556478858,25 -21809,1517556510398,25 -21810,1517556721779,25 -21811,1517557114622,25 -21812,1517557277423,24 -21813,1517557352734,23 -21814,1517557416402,23 -21815,1517557469797,23 -21816,1517557559446,22 -21817,1517557630562,21 -21818,1517557669133,21 -21819,1517557722297,21 -21820,1517557754369,21 -21821,1517557792742,22 -21822,1517557840887,22 -21823,1517557878707,21 -21824,1517557907981,22 -21825,1517557931004,22 -21826,1517557972015,23 -21827,1517558036972,23 -21828,1517558096325,22 -21829,1517558122493,22 -21830,1517558255714,22 -21831,1517558329724,21 -21832,1517558419719,21 -21833,1517558513762,20 -21834,1517558552100,19 -21835,1517558626501,19 -21836,1517558710296,18 -21837,1517558802798,18 -21838,1517558877319,17 -21839,1517558912113,16 -21840,1517559183441,16 -21841,1517559206565,16 -21842,1517559258136,17 -21843,1517559309506,18 -21844,1517564007393,20 -21845,1517564093132,22 -21846,1517564145826,21 -21847,1517564206761,22 -21848,1517564244311,22 -21849,1517564333941,22 -21850,1517564395040,21 -21851,1517564596675,21 -21852,1517564627903,20 -21853,1517564707517,21 -21854,1517564803786,21 -21855,1517564820613,21 -21856,1517564877162,23 -21857,1517564904882,23 -21858,1517564930230,23 -21859,1517564977050,25 -21860,1517565134592,25 -21861,1517565146555,24 -21862,1517565235907,28 -21863,1517565305846,27 -21864,1517565328058,26 -21865,1517565366718,28 -21866,1517565402529,30 -21867,1517565422246,32 -21868,1517565431061,35 -21869,1517565447883,43 -21870,1517565525115,48 -21871,1517565565883,48 -21872,1517565652386,50 -21873,1517565716278,50 -21874,1517565779933,49 -21875,1517565789181,50 -21876,1517565795600,61 -21877,1517565915442,82 -21878,1517565954408,83 -21879,1517566011603,87 -21880,1517566142319,89 -21881,1517566489596,87 -21882,1517566570036,86 -21883,1517566584540,86 -21884,1517566911836,99 -21885,1517567164013,97 -21886,1517567319247,96 -21887,1517567384079,95 -21888,1517567409663,95 -21889,1517567468793,102 -21890,1517567592219,104 -21891,1517567806935,103 -21892,1517567981008,102 -21893,1517568030530,101 -21894,1517568336521,103 -21895,1517568357211,102 -21896,1517568559111,113 -21897,1517568574099,112 -21898,1517568601733,127 -21899,1517569038501,134 -21900,1517569072659,132 -21901,1517569262001,138 -21902,1517569325682,137 -21903,1517569431276,138 -21904,1517569446146,138 -21905,1517569901865,156 -21906,1517570125471,154 -21907,1517570574373,151 -21908,1517570594376,149 -21909,1517570608979,162 -21910,1517570626089,185 -21911,1517571187910,207 -21912,1517571323217,203 -21913,1517571456375,201 -21914,1517571701473,200 -21915,1517571859906,196 -21916,1517572173301,195 -21917,1517572389874,192 -21918,1517572393665,189 -21919,1517572649270,304 -21920,1517572910042,300 -21921,1517573126201,296 -21922,1517574120473,293 -21923,1517574689769,287 -21924,1517574962557,281 -21925,1517575138731,277 -21926,1517576050401,275 -21927,1517576134411,269 -21928,1517576652182,271 -21929,1517577418755,265 -21930,1517577785397,259 -21931,1517577932149,253 -21932,1517578258604,250 -21933,1517578876413,245 -21934,1517578885608,239 -21935,1517579154750,295 -21936,1517579789371,289 -21937,1517581326849,282 -21938,1517581909890,275 -21939,1517582051011,267 -21940,1517582356807,264 -21941,1517583047423,258 -21942,1517583271007,250 -21943,1517583433575,245 -21944,1517584892389,241 -21945,1517585163525,232 -21946,1517585440802,226 -21947,1517585568031,220 -21948,1517586042745,216 -21949,1517586970894,209 -21950,1517587269893,201 -21951,1517587335554,195 -21952,1517587466794,193 -21953,1517587727220,189 -21954,1517587944512,182 -21955,1517588177650,175 -21956,1517588186938,170 -21957,1517588234667,205 -21958,1517588268367,207 -21959,1517588808836,213 -21960,1517589158102,206 -21961,1517589216728,197 -21962,1517589785762,198 -21963,1517590114535,189 -21964,1517590118427,181 -21965,1517590212065,284 -21966,1517590480207,281 -21967,1517590539767,272 -21968,1517590887002,274 -21969,1517591264837,269 -21970,1517591349363,263 -21971,1517591943138,259 -21972,1517592325802,250 -21973,1517592406292,241 -21974,1517592777015,237 -21975,1517593000819,228 -21976,1517593423647,226 -21977,1517593750223,227 -21978,1517593843590,218 -21979,1517594551522,215 -21980,1517594670689,206 -21981,1517594741098,201 -21982,1517594966410,197 -21983,1517595107336,189 -21984,1517595148727,188 -21985,1517595344498,188 -21986,1517595374730,179 -21987,1517595643218,183 -21988,1517596109003,175 -21989,1517596739209,169 -21990,1517596780849,161 -21991,1517596961151,160 -21992,1517597150732,151 -21993,1517597178194,142 -21994,1517597350040,146 -21995,1517597367141,136 -21996,1517597763862,151 -21997,1517597818735,140 -21998,1517597825269,143 -21999,1517597944037,190 -22000,1517598020704,183 -22001,1517598271747,181 -22002,1517598295306,172 -22003,1517598488858,180 -22004,1517598777145,171 -22005,1517599206699,171 -22006,1517599262753,162 -22007,1517599489857,157 -22008,1517599510126,147 -22009,1517599546818,162 -22010,1517599703446,174 -22011,1517600148559,178 -22012,1517600702662,168 -22013,1517600824632,159 -22014,1517600844473,153 -22015,1517600932494,160 -22016,1517600990740,155 -22017,1517601111359,151 -22018,1517601586689,143 -22019,1517601838137,194 -22020,1517601900660,187 -22021,1517602589256,186 -22022,1517603184088,177 -22023,1517604225238,169 -22024,1517604291002,160 -22025,1517604467843,157 -22026,1517604834795,152 -22027,1517605203354,143 -22028,1517605518435,137 -22029,1517605652946,129 -22030,1517605921861,122 -22031,1517606450934,114 -22032,1517606666394,107 -22033,1517606770757,99 -22034,1517606947878,92 -22035,1517607093325,116 -22036,1517607246157,110 -22037,1517607682237,103 -22038,1517607713563,95 -22039,1517607747179,94 -22040,1517608051626,94 -22041,1517608250469,86 -22042,1517608394665,80 -22043,1517608482556,73 -22044,1517608550444,68 -22045,1517608581716,62 -22046,1517608794862,58 -22047,1517608812142,50 -22048,1517608824463,51 -22049,1517608844191,52 -22050,1517608858798,50 -22051,1517608879218,49 -22052,1517608891012,49 -22053,1517608943173,52 -22054,1517609014490,46 -22055,1517609072011,38 -22056,1517609270293,31 -22057,1517609285141,46 -22058,1517609391103,49 -22059,1517609443415,49 -22060,1517609473790,43 -22061,1517609506911,39 -22062,1517609546163,37 -22063,1517609716391,31 -22064,1517609741732,23 -22065,1517609761158,75 -22066,1517609767680,81 -22067,1517609985445,105 -22068,1517609997517,104 -22069,1517610046771,119 -22070,1517610370609,118 -22071,1517610600134,116 -22072,1517610638644,110 -22073,1517610645406,110 -22074,1517610657356,145 -22075,1517610922204,167 -22076,1517611101640,161 -22077,1517611809229,156 -22078,1517612157447,149 -22079,1517612164021,145 -22080,1517612170606,190 -22081,1517612471232,252 -22082,1517613187006,247 -22083,1517613547321,239 -22084,1517613896379,232 -22085,1517613916341,230 -22086,1517614032870,248 -22087,1517614581342,250 -22088,1517614730080,242 -22089,1517615628697,236 -22090,1517616252889,227 -22091,1517616256531,223 -22092,1517616735730,361 -22093,1517617156705,351 -22094,1517618337203,348 -22095,1517618720885,337 -22096,1517619349467,338 -22097,1517621231142,327 -22098,1517621285881,319 -22099,1517621300063,349 -22100,1517621762293,399 -22101,1517623078211,391 -22102,1517623262835,381 -22103,1517624058649,384 -22104,1517625642490,374 -22105,1517626130272,364 -22106,1517626428632,354 -22107,1517626766686,349 -22108,1517627067330,341 -22109,1517627468954,341 -22110,1517627595715,338 -22111,1517628504111,334 -22112,1517628582067,323 -22113,1517628785419,323 -22114,1517628875975,317 -22115,1517629530953,323 -22116,1517630234829,316 -22117,1517630506129,308 -22118,1517630770815,302 -22119,1517631095277,294 -22120,1517631920367,285 -22121,1517632924291,279 -22122,1517633203335,269 -22123,1517633434838,260 -22124,1517633516221,252 -22125,1517634002562,251 -22126,1517634214058,242 -22127,1517634590493,234 -22128,1517634950440,225 -22129,1517635134690,216 -22130,1517635537287,209 -22131,1517635826605,200 -22132,1517635949094,190 -22133,1517636188708,183 -22134,1517636507435,175 -22135,1517636716747,165 -22136,1517636748353,157 -22137,1517636789797,158 -22138,1517637245004,156 -22139,1517637391516,149 -22140,1517637627073,143 -22141,1517637707548,134 -22142,1517637850872,128 -22143,1517638041859,119 -22144,1517638600432,110 -22145,1517638647357,100 -22146,1517638786406,96 -22147,1517638973387,87 -22148,1517638993061,80 -22149,1517639152065,84 -22150,1517639204283,77 -22151,1517639248934,74 -22152,1517639412086,69 -22153,1517639542934,63 -22154,1517639546661,55 -22155,1517639561365,80 -22156,1517639733534,83 -22157,1517639771395,72 -22158,1517639929720,69 -22159,1517640076887,59 -22160,1517640091663,49 -22161,1517640095804,48 -22162,1517640147303,65 -22163,1517640248640,57 -22164,1517640371095,46 -22165,1517640385676,36 -22166,1517640461302,35 -22167,1517640484043,39 -22168,1517640711075,32 -22169,1517640750235,31 -22170,1517640789232,25 -22171,1517640806035,16 -22172,1517640812809,7 -22173,1517640822111,2 -22174,1517640826208,11 -22175,1517640838375,22 -22176,1517640849998,17 -22177,1517640856471,11 -22178,1517640877137,4 -22179,1517640889036,1 -22180,1517640893094,13 -22181,1517640940857,46 -22182,1517640993059,41 -22183,1517641035067,34 -22184,1517641279602,28 -22185,1517641291358,20 -22186,1517641303088,31 -22187,1517641366478,31 -22188,1517641375348,25 -22189,1517641384216,25 -22190,1517641464979,23 -22191,1517641479328,15 -22192,1517641482955,86 -22193,1517641518730,137 -22194,1517641652301,140 -22195,1517641944887,136 -22196,1517642265588,130 -22197,1517642431704,125 -22198,1517642515086,120 -22199,1517643135123,123 -22200,1517643214497,147 -22201,1517643221094,146 -22202,1517643607560,193 -22203,1517643974740,189 -22204,1517644053993,185 -22205,1517644350229,183 -22206,1517644498974,178 -22207,1517644585427,176 -22208,1517644774693,175 -22209,1517644837176,171 -22210,1517644917274,171 -22211,1517644929492,173 -22212,1517645581858,201 -22213,1517645845761,199 -22214,1517645863106,195 -22215,1517646228084,218 -22216,1517646689336,212 -22217,1517646754141,207 -22218,1517647101099,208 -22219,1517647909677,203 -22220,1517647922116,197 -22221,1517648300755,227 -22222,1517648799212,221 -22223,1517649558957,214 -22224,1517649944341,208 -22225,1517650213614,205 -22226,1517651046581,199 -22227,1517651218684,192 -22228,1517651270814,188 -22229,1517651559829,189 -22230,1517652036313,183 -22231,1517652199224,176 -22232,1517652235182,172 -22233,1517653300390,177 -22234,1517653362304,170 -22235,1517653531688,168 -22236,1517653647568,163 -22237,1517653715102,165 -22238,1517654399796,166 -22239,1517654661007,159 -22240,1517654836396,154 -22241,1517654928330,148 -22242,1517654999294,146 -22243,1517655598645,143 -22244,1517655647547,136 -22245,1517655746984,135 -22246,1517655829754,132 -22247,1517655916483,128 -22248,1517656073899,124 -22249,1517656181329,123 -22250,1517656341613,117 -22251,1517656526037,113 -22252,1517656704218,108 -22253,1517656726992,101 -22254,1517656733671,105 -22255,1517656751298,151 -22256,1517657053533,170 -22257,1517657102194,164 -22258,1517657471929,165 -22259,1517657491722,158 -22260,1517657509198,169 -22261,1517657699271,188 -22262,1517658375106,195 -22263,1517658460278,189 -22264,1517658783095,186 -22265,1517658818302,179 -22266,1517658846393,185 -22267,1517659408018,192 -22268,1517659572565,186 -22269,1517659705771,180 -22270,1517659753054,174 -22271,1517659897667,176 -22272,1517660233224,170 -22273,1517660433749,163 -22274,1517660566984,156 -22275,1517660807522,153 -22276,1517660841461,147 -22277,1517660966150,151 -22278,1517661350440,146 -22279,1517661950360,138 -22280,1517662395643,129 -22281,1517663209223,125 -22282,1517663265317,117 -22283,1517663589054,114 -22284,1517663608962,106 -22285,1517663642853,110 -22286,1517663729648,111 -22287,1517664077372,107 -22288,1517664111299,100 -22289,1517664821407,100 -22290,1517665021194,95 -22291,1517665457504,87 -22292,1517665579250,80 -22293,1517665612425,101 -22294,1517665619068,105 -22295,1517665718574,136 -22296,1517665860168,131 -22297,1517665902258,124 -22298,1517665993738,123 -22299,1517666421380,120 -22300,1517666519547,111 -22301,1517666739359,107 -22302,1517666761745,127 -22303,1517666787001,132 -22304,1517666923151,137 -22305,1517667034029,134 -22306,1517667224651,128 -22307,1517667528566,123 -22308,1517667804071,118 -22309,1517668132919,112 -22310,1517668264462,107 -22311,1517668399585,104 -22312,1517668593325,114 -22313,1517668691674,109 -22314,1517668720271,104 -22315,1517668811191,119 -22316,1517669088306,115 -22317,1517669391911,109 -22318,1517669566941,106 -22319,1517669694300,101 -22320,1517669746906,96 -22321,1517670085568,112 -22322,1517670142053,106 -22323,1517670370074,104 -22324,1517670406780,98 -22325,1517670668559,99 -22326,1517670759862,93 -22327,1517670928298,89 -22328,1517671048287,84 -22329,1517671084880,83 -22330,1517671145754,82 -22331,1517671171164,79 -22332,1517671251617,80 -22333,1517671440910,81 -22334,1517671659909,76 -22335,1517671724805,73 -22336,1517671904447,70 -22337,1517672041837,65 -22338,1517672119749,63 -22339,1517672188602,58 -22340,1517672311469,54 -22341,1517672368133,49 -22342,1517672377260,46 -22343,1517672428086,54 -22344,1517672622997,50 -22345,1517672658903,47 -22346,1517672725240,44 -22347,1517672739680,41 -22348,1517672819673,43 -22349,1517672956025,38 -22350,1517673022560,33 -22351,1517673123187,28 -22352,1517673200179,23 -22353,1517673279144,17 -22354,1517673296997,17 -22355,1517673371075,32 -22356,1517673445369,37 -22357,1517673557839,33 -22358,1517673648437,31 -22359,1517673660389,27 -22360,1517673672428,37 -22361,1517673735700,51 -22362,1517674034917,48 -22363,1517674142598,44 -22364,1517674350846,42 -22365,1517674463330,38 -22366,1517674596372,40 -22367,1517674667121,44 -22368,1517674671098,41 -22369,1517674710234,62 -22370,1517674759711,62 -22371,1517674801308,65 -22372,1517674886309,65 -22373,1517674895198,62 -22374,1517674918262,74 -22375,1517674995739,78 -22376,1517675084018,76 -22377,1517675208951,78 -22378,1517675512621,76 -22379,1517675543180,72 -22380,1517675549895,72 -22381,1517675553471,93 -22382,1517675989565,150 -22383,1517676039018,146 -22384,1517676081473,148 -22385,1517676541853,155 -22386,1517676746941,154 -22387,1517676934975,150 -22388,1517677052567,147 -22389,1517677238626,146 -22390,1517678690856,142 -22391,1517678801708,136 -22392,1517678893121,132 -22393,1517679038269,130 -22394,1517679073530,130 -22395,1517679360704,151 -22396,1517679435371,149 -22397,1517679632836,148 -22398,1517679812145,148 -22399,1517679893757,146 -22400,1517680219898,145 -22401,1517680772202,140 -22402,1517680864963,136 -22403,1517681458065,141 -22404,1517681621055,141 -22405,1517681681972,139 -22406,1517681829239,141 -22407,1517681846563,138 -22408,1517681906406,152 -22409,1517681963706,152 -22410,1517682102893,154 -22411,1517682188401,151 -22412,1517682381424,150 -22413,1517682438835,146 -22414,1517682852618,148 -22415,1517682886395,147 -22416,1517683261308,152 -22417,1517683360988,148 -22418,1517683397239,146 -22419,1517683877493,150 -22420,1517683970651,145 -22421,1517684001619,145 -22422,1517684322679,150 -22423,1517684367225,147 -22424,1517684718184,149 -22425,1517684848977,147 -22426,1517684923376,144 -22427,1517685000053,143 -22428,1517685149352,141 -22429,1517685223103,138 -22430,1517685393198,138 -22431,1517685658827,135 -22432,1517685673194,135 -22433,1517685903709,151 -22434,1517685981973,147 -22435,1517686014452,145 -22436,1517686020858,150 -22437,1517686673350,200 -22438,1517686714675,194 -22439,1517686802956,197 -22440,1517686826688,196 -22441,1517686961204,209 -22442,1517687729954,205 -22443,1517687796281,204 -22444,1517687989680,204 -22445,1517688356935,199 -22446,1517688602899,193 -22447,1517688846724,188 -22448,1517689638792,185 -22449,1517689800758,178 -22450,1517690082930,173 -22451,1517690348994,167 -22452,1517690520520,161 -22453,1517690615740,155 -22454,1517690637678,151 -22455,1517690769198,160 -22456,1517691167350,155 -22457,1517691460595,148 -22458,1517691576793,141 -22459,1517691831716,136 -22460,1517692100667,132 -22461,1517692104455,129 -22462,1517692284463,203 -22463,1517693101090,197 -22464,1517693121356,188 -22465,1517693948861,201 -22466,1517694075954,192 -22467,1517694501637,186 -22468,1517694676915,178 -22469,1517694773065,183 -22470,1517694816956,179 -22471,1517695576036,181 -22472,1517695744370,174 -22473,1517695840931,168 -22474,1517695938300,171 -22475,1517696004274,170 -22476,1517696029382,167 -22477,1517696424433,175 -22478,1517696446787,167 -22479,1517696469767,176 -22480,1517696546582,187 -22481,1517696655216,196 -22482,1517696702416,223 -22483,1517696722590,226 -22484,1517697128122,247 -22485,1517697595256,243 -22486,1517697697945,235 -22487,1517698024295,232 -22488,1517698219114,226 -22489,1517698574388,221 -22490,1517698697635,213 -22491,1517698718003,209 -22492,1517700034565,225 -22493,1517701426555,217 -22494,1517701543686,209 -22495,1517702039920,208 -22496,1517702718792,200 -22497,1517703128232,194 -22498,1517703363638,186 -22499,1517704123639,179 -22500,1517704817528,173 -22501,1517705047855,165 -22502,1517705176324,156 -22503,1517706305138,152 -22504,1517706438952,143 -22505,1517706462211,137 -22506,1517706858246,145 -22507,1517707663994,137 -22508,1517707886931,138 -22509,1517708131309,134 -22510,1517708515501,128 -22511,1517708737847,122 -22512,1517709053008,115 -22513,1517709118998,108 -22514,1517709225798,106 -22515,1517709345511,100 -22516,1517709352423,99 -22517,1517709386758,124 -22518,1517709406298,126 -22519,1517709671259,136 -22520,1517709994903,128 -22521,1517710046797,122 -22522,1517710160682,123 -22523,1517710186794,117 -22524,1517710286422,122 -22525,1517710300536,116 -22526,1517711342152,127 -22527,1517711588197,120 -22528,1517711876955,114 -22529,1517711888882,106 -22530,1517712233709,120 -22531,1517712261844,112 -22532,1517712352549,112 -22533,1517712665977,116 -22534,1517712716043,108 -22535,1517712768787,106 -22536,1517712861067,107 -22537,1517713089519,129 -22538,1517713169968,121 -22539,1517713295160,122 -22540,1517713387753,118 -22541,1517713880489,123 -22542,1517714115717,117 -22543,1517714387643,110 -22544,1517714472854,106 -22545,1517714659964,102 -22546,1517714668682,96 -22547,1517714710269,114 -22548,1517714782875,114 -22549,1517714900071,108 -22550,1517714961255,103 -22551,1517715173793,99 -22552,1517715519250,92 -22553,1517715710319,85 -22554,1517715743966,79 -22555,1517715828313,85 -22556,1517715937211,80 -22557,1517715954520,74 -22558,1517716025334,76 -22559,1517716145172,71 -22560,1517716292321,64 -22561,1517716484324,57 -22562,1517716605415,91 -22563,1517717079974,87 -22564,1517717134012,80 -22565,1517717419882,87 -22566,1517717573268,81 -22567,1517717734795,77 -22568,1517718043265,71 -22569,1517718058126,66 -22570,1517718176584,72 -22571,1517718232764,71 -22572,1517718456398,67 -22573,1517718595541,61 -22574,1517718609736,58 -22575,1517718663506,63 -22576,1517718745450,61 -22577,1517718813315,65 -22578,1517718997738,60 -22579,1517719022825,63 -22580,1517719215266,72 -22581,1517719241012,70 -22582,1517719306139,72 -22583,1517719382014,73 -22584,1517719420909,84 -22585,1517719488179,83 -22586,1517719525235,81 -22587,1517719540069,83 -22588,1517719746734,91 -22589,1517720342403,88 -22590,1517720421490,83 -22591,1517720501309,81 -22592,1517720529236,89 -22593,1517720557508,92 -22594,1517720561237,94 -22595,1517720614130,151 -22596,1517720799610,151 -22597,1517721603803,147 -22598,1517721909006,140 -22599,1517722147175,135 -22600,1517722217171,130 -22601,1517722372997,127 -22602,1517722395989,124 -22603,1517722473336,131 -22604,1517722598844,128 -22605,1517722640409,124 -22606,1517722968186,132 -22607,1517723133057,126 -22608,1517723498375,121 -22609,1517723663702,115 -22610,1517723776578,110 -22611,1517723880645,105 -22612,1517723903371,101 -22613,1517723912714,105 -22614,1517723946266,127 -22615,1517723963450,129 -22616,1517724135119,141 -22617,1517724411551,152 -22618,1517724543976,151 -22619,1517725038225,153 -22620,1517725294616,147 -22621,1517725366191,142 -22622,1517725434976,142 -22623,1517725693994,141 -22624,1517725800849,141 -22625,1517726438440,139 -22626,1517727200709,142 -22627,1517727315656,137 -22628,1517727410491,133 -22629,1517727515938,130 -22630,1517727594273,137 -22631,1517727829841,135 -22632,1517727945670,134 -22633,1517728086297,132 -22634,1517728383349,128 -22635,1517729120385,125 -22636,1517729276341,122 -22637,1517729385278,119 -22638,1517729482906,116 -22639,1517729960794,114 -22640,1517730189566,109 -22641,1517730307358,105 -22642,1517730464366,101 -22643,1517730536239,97 -22644,1517730578791,94 -22645,1517730861555,94 -22646,1517730969251,89 -22647,1517731142992,98 -22648,1517731201897,97 -22649,1517731761131,97 -22650,1517731951081,92 -22651,1517732080318,89 -22652,1517732179220,86 -22653,1517732224157,82 -22654,1517732266367,82 -22655,1517732299346,82 -22656,1517732390672,84 -22657,1517732456653,81 -22658,1517732501596,83 -22659,1517732711419,83 -22660,1517732747450,78 -22661,1517732832470,78 -22662,1517732973417,75 -22663,1517733020283,71 -22664,1517733040495,68 -22665,1517733138934,72 -22666,1517733246135,69 -22667,1517733279555,65 -22668,1517733762502,64 -22669,1517733857160,58 -22670,1517733885528,58 -22671,1517733900311,58 -22672,1517733957739,62 -22673,1517733974892,59 -22674,1517734118680,62 -22675,1517734247228,61 -22676,1517734397984,57 -22677,1517734466759,53 -22678,1517734502478,50 -22679,1517734514208,47 -22680,1517734548208,53 -22681,1517734595176,51 -22682,1517734628006,52 -22683,1517734747583,51 -22684,1517734809008,45 -22685,1517734861014,44 -22686,1517734916379,41 -22687,1517734954166,40 -22688,1517734985309,43 -22689,1517735172373,40 -22690,1517735308029,35 -22691,1517735346603,31 -22692,1517735369467,28 -22693,1517735395358,29 -22694,1517735466884,30 -22695,1517735478349,56 -22696,1517735593602,66 -22697,1517735657592,63 -22698,1517735774072,62 -22699,1517735777985,58 -22700,1517735818885,89 -22701,1517736050688,91 -22702,1517736062627,88 -22703,1517736195957,106 -22704,1517736317179,104 -22705,1517736529002,102 -22706,1517736650822,101 -22707,1517737048138,98 -22708,1517737057361,94 -22709,1517737377678,113 -22710,1517737411325,109 -22711,1517737534261,112 -22712,1517737864756,110 -22713,1517738128776,110 -22714,1517738445149,119 -22715,1517738545151,120 -22716,1517738678933,126 -22717,1517738816951,124 -22718,1517738909363,122 -22719,1517738989839,122 -22720,1517739130489,121 -22721,1517739393503,118 -22722,1517739521935,117 -22723,1517739607695,116 -22724,1517739820833,115 -22725,1517739827235,113 -22726,1517739844537,151 -22727,1517740078953,166 -22728,1517740353215,163 -22729,1517740357389,160 -22730,1517740461806,248 -22731,1517741376972,249 -22732,1517741441784,242 -22733,1517741871957,246 -22734,1517742209446,241 -22735,1517742249151,236 -22736,1517742260784,243 -22737,1517743762017,286 -22738,1517744140361,279 -22739,1517744147074,274 -22740,1517744201059,364 -22741,1517744557632,371 -22742,1517745224158,365 -22743,1517745751488,357 -22744,1517745844868,350 -22745,1517746301876,352 -22746,1517746356752,345 -22747,1517747619861,350 -22748,1517747665175,341 -22749,1517748250499,351 -22750,1517748375013,343 -22751,1517748854296,339 -22752,1517749099443,331 -22753,1517749907466,326 -22754,1517750088457,318 -22755,1517750314197,314 -22756,1517750789293,310 -22757,1517751869342,302 -22758,1517752205397,294 -22759,1517753574484,288 -22760,1517755137405,279 -22761,1517755220266,271 -22762,1517756473289,269 -22763,1517756788381,261 -22764,1517757134178,254 -22765,1517757376701,249 -22766,1517757427636,243 -22767,1517757541112,245 -22768,1517757877612,242 -22769,1517758240718,233 -22770,1517758269142,225 -22771,1517758297490,236 -22772,1517758470653,250 -22773,1517758485023,244 -22774,1517758658025,279 -22775,1517758721928,271 -22776,1517759038151,271 -22777,1517760019573,262 -22778,1517760031237,252 -22779,1517760071092,294 -22780,1517760384840,304 -22781,1517760779308,296 -22782,1517761291611,287 -22783,1517761350977,278 -22784,1517761927751,278 -22785,1517762125001,267 -22786,1517762888543,259 -22787,1517763216354,248 -22788,1517763325422,239 -22789,1517763612499,233 -22790,1517763932956,223 -22791,1517763986557,213 -22792,1517764039800,211 -22793,1517764255350,209 -22794,1517764566967,200 -22795,1517764611666,189 -22796,1517764710893,193 -22797,1517765221312,185 -22798,1517765687845,175 -22799,1517766102714,164 -22800,1517766109307,171 -22801,1517766544298,223 -22802,1517766599843,212 -22803,1517767004780,217 -22804,1517767013895,206 -22805,1517767144959,249 -22806,1517767240095,240 -22807,1517767315223,233 -22808,1517767333043,227 -22809,1517767428309,257 -22810,1517767619199,250 -22811,1517767657785,242 -22812,1517768795280,245 -22813,1517769123787,232 -22814,1517769838278,220 -22815,1517769877738,207 -22816,1517769915389,206 -22817,1517770475781,206 -22818,1517770512249,194 -22819,1517770555484,193 -22820,1517770722060,191 -22821,1517771290173,181 -22822,1517771391604,167 -22823,1517771471189,157 -22824,1517772055042,148 -22825,1517772366978,135 -22826,1517772621451,143 -22827,1517773295952,141 -22828,1517773463559,129 -22829,1517773549194,117 -22830,1517773930554,154 -22831,1517773963998,145 -22832,1517774165768,144 -22833,1517774235764,137 -22834,1517774384304,131 -22835,1517774555969,120 -22836,1517774569885,117 -22837,1517774957568,151 -22838,1517775121125,140 -22839,1517775447784,131 -22840,1517775485187,171 -22841,1517775499633,179 -22842,1517775901682,199 -22843,1517776225380,191 -22844,1517776509673,183 -22845,1517776685448,177 -22846,1517777599470,171 -22847,1517777703503,168 -22848,1517778296668,161 -22849,1517778434751,161 -22850,1517778523160,154 -22851,1517778764525,152 -22852,1517779050700,144 -22853,1517779794353,137 -22854,1517779806195,127 -22855,1517780463441,145 -22856,1517780531058,137 -22857,1517781227244,132 -22858,1517781403899,122 -22859,1517781429810,114 -22860,1517781490713,114 -22861,1517781519137,109 -22862,1517781708894,112 -22863,1517781726464,102 -22864,1517781902200,106 -22865,1517782107337,98 -22866,1517782349266,90 -22867,1517782465757,85 -22868,1517782608602,78 -22869,1517782778607,70 -22870,1517782796194,62 -22871,1517782833395,69 -22872,1517782837609,73 -22873,1517782841324,106 -22874,1517782907291,184 -22875,1517783037313,182 -22876,1517783041225,179 -22877,1517783540621,279 -22878,1517783655964,268 -22879,1517783744748,287 -22880,1517784084762,291 -22881,1517784283513,283 -22882,1517784519374,275 -22883,1517784922187,267 -22884,1517785103593,262 -22885,1517785523570,254 -22886,1517785535725,245 -22887,1517785610421,282 -22888,1517785981349,280 -22889,1517786158929,271 -22890,1517786396640,263 -22891,1517786613795,254 -22892,1517786718421,249 -22893,1517787049124,247 -22894,1517787218892,238 -22895,1517788402228,229 -22896,1517788922772,222 -22897,1517789090806,213 -22898,1517789236385,204 -22899,1517789765529,196 -22900,1517790084829,184 -22901,1517790166628,206 -22902,1517790263364,200 -22903,1517790281306,199 -22904,1517790365366,214 -22905,1517790454346,236 -22906,1517790512802,234 -22907,1517790729249,236 -22908,1517790795948,230 -22909,1517791221511,243 -22910,1517791249868,237 -22911,1517791671930,248 -22912,1517791744481,246 -22913,1517792295170,244 -22914,1517792563125,234 -22915,1517792611208,225 -22916,1517793108509,233 -22917,1517793234165,229 -22918,1517793420696,223 -22919,1517793637486,222 -22920,1517793641240,219 -22921,1517794413846,351 -22922,1517795209158,339 -22923,1517795649286,329 -22924,1517796446571,321 -22925,1517796544458,310 -22926,1517796948868,305 -22927,1517797023910,296 -22928,1517797256135,292 -22929,1517798353595,283 -22930,1517798570717,273 -22931,1517798653147,263 -22932,1517798994775,264 -22933,1517799217071,253 -22934,1517799305620,246 -22935,1517799318256,242 -22936,1517799516816,275 -22937,1517799635960,275 -22938,1517799723883,268 -22939,1517800881619,263 -22940,1517801315168,250 -22941,1517802135699,244 -22942,1517802416983,247 -22943,1517802650761,237 -22944,1517802825529,227 -22945,1517803115571,218 -22946,1517803290857,209 -22947,1517803370781,199 -22948,1517803402534,195 -22949,1517803480764,197 -22950,1517803536049,191 -22951,1517803991738,188 -22952,1517804203651,177 -22953,1517804415074,166 -22954,1517804517745,154 -22955,1517805026990,158 -22956,1517805031049,146 -22957,1517805180253,222 -22958,1517805521350,212 -22959,1517806497219,200 -22960,1517806553439,192 -22961,1517806584940,188 -22962,1517807526648,193 -22963,1517807775037,180 -22964,1517808105519,175 -22965,1517808137199,163 -22966,1517808228395,162 -22967,1517808457294,153 -22968,1517808494867,141 -22969,1517808598961,136 -22970,1517808901519,126 -22971,1517809001197,117 -22972,1517809045941,107 -22973,1517809057908,120 -22974,1517809163117,166 -22975,1517809275538,161 -22976,1517809610502,153 -22977,1517810122340,197 -22978,1517810252709,188 -22979,1517810686673,183 -22980,1517810942101,177 -22981,1517810956947,168 -22982,1517810997112,186 -22983,1517811030981,187 -22984,1517811597309,189 -22985,1517812019506,180 -22986,1517812364339,169 -22987,1517812428405,184 -22988,1517812872032,185 -22989,1517813128590,175 -22990,1517813289885,168 -22991,1517813703138,161 -22992,1517813736807,152 -22993,1517813878611,156 -22994,1517813887812,148 -22995,1517814028296,177 -22996,1517814255702,168 -22997,1517814558912,159 -22998,1517814878281,151 -22999,1517814948335,142 -23000,1517814999306,135 -23001,1517815425427,131 -23002,1517815689207,123 -23003,1517815941960,115 -23004,1517815950836,119 -23005,1517816105538,143 -23006,1517816267347,136 -23007,1517816630931,132 -23008,1517816796047,123 -23009,1517817058806,117 -23010,1517817131906,108 -23011,1517817300830,110 -23012,1517817621141,102 -23013,1517817659836,95 -23014,1517817767408,92 -23015,1517817874825,83 -23016,1517818069131,80 -23017,1517818109425,70 -23018,1517818201143,66 -23019,1517818405616,58 -23020,1517818585448,49 -23021,1517818613693,112 -23022,1517818848134,113 -23023,1517818917784,106 -23024,1517820159938,101 -23025,1517820337154,94 -23026,1517820370624,90 -23027,1517820524268,89 -23028,1517820685729,86 -23029,1517820903784,80 -23030,1517820934627,73 -23031,1517821039758,72 -23032,1517821063006,68 -23033,1517821183373,68 -23034,1517821253587,62 -23035,1517821318136,58 -23036,1517821365528,75 -23037,1517821407929,74 -23038,1517821475059,72 -23039,1517821514335,71 -23040,1517821518395,67 -23041,1517821530770,100 -23042,1517821878745,111 -23043,1517822008571,105 -23044,1517822053696,99 -23045,1517822943578,98 -23046,1517822955700,89 -23047,1517823074428,100 -23048,1517823691305,96 -23049,1517823761164,95 -23050,1517823777902,93 -23051,1517823975554,102 -23052,1517824022662,95 -23053,1517824045883,92 -23054,1517824436049,93 -23055,1517824634394,87 -23056,1517824721149,79 -23057,1517824838984,118 -23058,1517824914358,114 -23059,1517824943514,111 -23060,1517824966680,113 -23061,1517824980957,121 -23062,1517825438205,141 -23063,1517825450433,134 -23064,1517825560187,154 -23065,1517825756462,150 -23066,1517825848479,150 -23067,1517825910745,147 -23068,1517826177942,146 -23069,1517826257494,144 -23070,1517826280346,141 -23071,1517826664051,149 -23072,1517827982245,142 -23073,1517828145787,137 -23074,1517828449702,144 -23075,1517828582807,139 -23076,1517828586468,136 -23077,1517828642941,217 -23078,1517828946434,218 -23079,1517829075946,212 -23080,1517829491405,207 -23081,1517829519716,200 -23082,1517829679781,222 -23083,1517829953637,222 -23084,1517830014760,222 -23085,1517830200551,222 -23086,1517830522022,217 -23087,1517831703013,210 -23088,1517831715254,205 -23089,1517832010639,237 -23090,1517832684523,230 -23091,1517832769925,222 -23092,1517833310660,220 -23093,1517833700295,217 -23094,1517834423677,210 -23095,1517834987260,221 -23096,1517835064952,215 -23097,1517835279645,214 -23098,1517835296586,209 -23099,1517835342437,230 -23100,1517836110743,235 -23101,1517837041462,230 -23102,1517837516519,221 -23103,1517838889065,213 -23104,1517839169854,206 -23105,1517839643478,214 -23106,1517839741015,208 -23107,1517839871778,205 -23108,1517839916672,201 -23109,1517839931227,204 -23110,1517840250995,228 -23111,1517840602496,223 -23112,1517840788184,215 -23113,1517840948679,210 -23114,1517841131845,206 -23115,1517841279061,200 -23116,1517841461416,195 -23117,1517841517722,189 -23118,1517841737968,189 -23119,1517842079425,182 -23120,1517842428122,175 -23121,1517843179912,167 -23122,1517843186269,162 -23123,1517843313419,215 -23124,1517843623460,210 -23125,1517843671105,202 -23126,1517843864211,202 -23127,1517844063799,197 -23128,1517844148374,190 -23129,1517844162805,185 -23130,1517845089877,206 -23131,1517845879947,199 -23132,1517845889442,189 -23133,1517845948041,229 -23134,1517846217768,228 -23135,1517846305555,219 -23136,1517846583304,215 -23137,1517846677007,207 -23138,1517846958214,202 -23139,1517847619696,194 -23140,1517847717751,186 -23141,1517847779071,198 -23142,1517848131111,205 -23143,1517848230826,196 -23144,1517848262082,191 -23145,1517848748115,197 -23146,1517849758503,187 -23147,1517849987893,186 -23148,1517850391819,177 -23149,1517850564963,168 -23150,1517850579632,162 -23151,1517850791309,184 -23152,1517851055781,176 -23153,1517851313660,169 -23154,1517851570300,163 -23155,1517851582137,155 -23156,1517851648358,176 -23157,1517851660216,172 -23158,1517851909288,196 -23159,1517852003040,189 -23160,1517852157332,186 -23161,1517852340069,183 -23162,1517852386886,184 -23163,1517852556004,183 -23164,1517852679377,187 -23165,1517852921990,181 -23166,1517852944904,173 -23167,1517853049046,182 -23168,1517853525439,177 -23169,1517853620936,168 -23170,1517853978862,163 -23171,1517854682181,160 -23172,1517854711009,150 -23173,1517855045798,151 -23174,1517855266335,142 -23175,1517855507539,132 -23176,1517855585270,123 -23177,1517855594294,162 -23178,1517855625935,200 -23179,1517855911074,205 -23180,1517856045844,198 -23181,1517856438112,192 -23182,1517856655245,191 -23183,1517856725117,184 -23184,1517856748131,181 -23185,1517856834494,194 -23186,1517857485863,190 -23187,1517858332645,181 -23188,1517858769691,170 -23189,1517858959917,181 -23190,1517859960172,174 -23191,1517860221013,165 -23192,1517860257609,160 -23193,1517860421864,161 -23194,1517860586962,153 -23195,1517860673656,146 -23196,1517860867855,140 -23197,1517861194744,135 -23198,1517861334394,127 -23199,1517861784857,134 -23200,1517861871220,131 -23201,1517862401809,125 -23202,1517862515150,117 -23203,1517862813126,110 -23204,1517863379788,101 -23205,1517863448717,93 -23206,1517863634413,87 -23207,1517863663000,81 -23208,1517863743020,81 -23209,1517863768865,78 -23210,1517863908644,93 -23211,1517863936759,87 -23212,1517863992360,86 -23213,1517864106472,82 -23214,1517864134227,75 -23215,1517864329698,74 -23216,1517864516652,68 -23217,1517864528795,61 -23218,1517864572549,67 -23219,1517864590438,63 -23220,1517864594575,63 -23221,1517864636941,90 -23222,1517864753268,86 -23223,1517865017242,109 -23224,1517865084874,103 -23225,1517865388445,98 -23226,1517865550625,95 -23227,1517865767280,89 -23228,1517865855244,82 -23229,1517865864580,78 -23230,1517866104543,105 -23231,1517866121323,98 -23232,1517866254016,103 -23233,1517866649773,120 -23234,1517867311647,118 -23235,1517868341869,111 -23236,1517868400245,107 -23237,1517868500034,104 -23238,1517868711486,101 -23239,1517868886552,95 -23240,1517869023547,89 -23241,1517869163248,85 -23242,1517869406077,82 -23243,1517869433539,76 -23244,1517869470675,76 -23245,1517869644067,82 -23246,1517869829640,75 -23247,1517870001716,68 -23248,1517870156394,63 -23249,1517870168319,57 -23250,1517870256946,62 -23251,1517870271966,69 -23252,1517870281363,74 -23253,1517870304053,85 -23254,1517870485323,88 -23255,1517870582296,82 -23256,1517870960257,92 -23257,1517871100278,88 -23258,1517871255094,100 -23259,1517871288226,95 -23260,1517871298023,98 -23261,1517871315028,116 -23262,1517871387745,127 -23263,1517871440394,128 -23264,1517871711433,128 -23265,1517871979761,123 -23266,1517872162929,118 -23267,1517872254207,122 -23268,1517872523348,119 -23269,1517873008831,114 -23270,1517873330513,110 -23271,1517873389044,104 -23272,1517873477250,101 -23273,1517873971354,103 -23274,1517874010803,97 -23275,1517874110852,96 -23276,1517874119998,93 -23277,1517874510026,112 -23278,1517874642558,127 -23279,1517874933942,130 -23280,1517875060821,126 -23281,1517875102251,123 -23282,1517875219900,125 -23283,1517875526516,121 -23284,1517875865150,119 -23285,1517876162549,123 -23286,1517876385667,121 -23287,1517876569911,116 -23288,1517877184907,112 -23289,1517877224937,106 -23290,1517877310601,107 -23291,1517877345241,104 -23292,1517877395020,105 -23293,1517877416107,110 -23294,1517877436985,118 -23295,1517877501051,126 -23296,1517877927572,126 -23297,1517878002598,120 -23298,1517878078679,118 -23299,1517878115231,116 -23300,1517878277766,117 -23301,1517878556383,114 -23302,1517878741672,109 -23303,1517879127640,104 -23304,1517879207288,99 -23305,1517879423529,95 -23306,1517879457667,91 -23307,1517879519453,91 -23308,1517879737783,91 -23309,1517879741420,87 -23310,1517879988180,141 -23311,1517880407480,136 -23312,1517880540345,133 -23313,1517880642549,129 -23314,1517880660938,126 -23315,1517880752063,138 -23316,1517881461520,135 -23317,1517881904989,128 -23318,1517882866507,128 -23319,1517882892286,122 -23320,1517883044181,130 -23321,1517883165633,144 -23322,1517883314526,143 -23323,1517883405330,138 -23324,1517883513186,136 -23325,1517883976425,133 -23326,1517884160420,128 -23327,1517884710619,123 -23328,1517884858652,117 -23329,1517884943236,113 -23330,1517884949914,120 -23331,1517884964695,157 -23332,1517885457091,182 -23333,1517885505797,176 -23334,1517885556529,179 -23335,1517885869835,179 -23336,1517885881736,172 -23337,1517885924430,202 -23338,1517886026710,207 -23339,1517886353631,204 -23340,1517886991294,198 -23341,1517887125715,190 -23342,1517887543182,186 -23343,1517888029160,179 -23344,1517888802209,175 -23345,1517890282643,170 -23346,1517890432169,163 -23347,1517890558442,157 -23348,1517890979147,152 -23349,1517891031681,145 -23350,1517891220067,150 -23351,1517891660261,144 -23352,1517892033278,142 -23353,1517892137146,145 -23354,1517892792282,145 -23355,1517892843140,139 -23356,1517893020002,138 -23357,1517893119325,133 -23358,1517893144904,128 -23359,1517893239020,134 -23360,1517893366041,133 -23361,1517893618702,140 -23362,1517893951098,142 -23363,1517894036200,138 -23364,1517894505066,137 -23365,1517894572972,131 -23366,1517894636765,129 -23367,1517894654207,127 -23368,1517894868431,139 -23369,1517895000388,134 -23370,1517895164559,128 -23371,1517895227898,123 -23372,1517895292969,123 -23373,1517895394037,121 -23374,1517895597619,115 -23375,1517895758187,112 -23376,1517896001077,108 -23377,1517896114872,114 -23378,1517896181105,109 -23379,1517896224251,107 -23380,1517896323381,106 -23381,1517896349198,102 -23382,1517896496305,108 -23383,1517896617958,103 -23384,1517896626780,98 -23385,1517896756488,118 -23386,1517896864109,113 -23387,1517896876124,108 -23388,1517896936280,123 -23389,1517897114924,119 -23390,1517897254444,116 -23391,1517897737606,112 -23392,1517897978909,107 -23393,1517898021477,104 -23394,1517898289116,108 -23395,1517898602807,108 -23396,1517898796443,103 -23397,1517899052845,97 -23398,1517899188007,92 -23399,1517899254050,88 -23400,1517899282419,88 -23401,1517899387336,89 -23402,1517899486412,83 -23403,1517899523519,78 -23404,1517899622642,76 -23405,1517899719152,72 -23406,1517899922420,66 -23407,1517899995780,62 -23408,1517900187655,58 -23409,1517900252008,52 -23410,1517900286752,77 -23411,1517900476596,76 -23412,1517900513170,70 -23413,1517900584539,69 -23414,1517900734202,66 -23415,1517900746488,69 -23416,1517900870896,78 -23417,1517900982419,72 -23418,1517901148711,67 -23419,1517901155162,62 -23420,1517901203013,84 -23421,1517901206728,82 -23422,1517901302994,130 -23423,1517901885892,127 -23424,1517902010520,121 -23425,1517902178008,117 -23426,1517902372415,112 -23427,1517902662158,106 -23428,1517902674147,99 -23429,1517902957836,112 -23430,1517903093116,107 -23431,1517903523931,123 -23432,1517903634102,130 -23433,1517903717188,126 -23434,1517903732334,127 -23435,1517903946787,144 -23436,1517903950534,139 -23437,1517903967455,240 -23438,1517903993042,272 -23439,1517904180636,291 -23440,1517904784171,287 -23441,1517905074293,280 -23442,1517905325607,276 -23443,1517905630462,270 -23444,1517906314638,264 -23445,1517908116647,256 -23446,1517909081777,248 -23447,1517909150542,242 -23448,1517909342685,243 -23449,1517909605174,238 -23450,1517909637141,234 -23451,1517910096240,244 -23452,1517910144366,237 -23453,1517910262212,240 -23454,1517910857940,238 -23455,1517911423122,230 -23456,1517911981826,225 -23457,1517912181536,218 -23458,1517912232301,213 -23459,1517912404245,221 -23460,1517912907184,216 -23461,1517913128215,210 -23462,1517913951231,204 -23463,1517914479915,196 -23464,1517915007747,190 -23465,1517915686439,182 -23466,1517915837312,176 -23467,1517916899740,172 -23468,1517918083013,173 -23469,1517919062232,166 -23470,1517919411117,159 -23471,1517919626816,152 -23472,1517919671878,147 -23473,1517920172083,149 -23474,1517920667645,143 -23475,1517920953024,136 -23476,1517920956922,130 -23477,1517921360428,202 -23478,1517921394353,195 -23479,1517921621810,200 -23480,1517921892691,196 -23481,1517922049662,189 -23482,1517922748285,187 -23483,1517922911820,179 -23484,1517923099058,173 -23485,1517923544309,179 -23486,1517923935456,172 -23487,1517924258041,165 -23488,1517924775780,168 -23489,1517925216584,163 -23490,1517925834712,156 -23491,1517926266799,149 -23492,1517926335119,141 -23493,1517926883343,138 -23494,1517927406607,133 -23495,1517928637098,125 -23496,1517930697204,117 -23497,1517931552728,108 -23498,1517931700640,100 -23499,1517932292001,95 -23500,1517932973803,88 -23501,1517933496095,83 -23502,1517933973366,76 -23503,1517934329805,68 -23504,1517934512742,63 -23505,1517934663860,56 -23506,1517935001444,49 -23507,1517935264314,42 -23508,1517935336586,35 -23509,1517935418826,28 -23510,1517935690870,21 -23511,1517935914991,16 -23512,1517935960126,9 -23513,1517935990215,3 -23514,1517936011464,1 -23515,1517936027399,1 -23516,1517936038379,1 -23517,1517936054728,1 -23518,1517936070834,1 -23519,1517936082392,1 -23520,1517936094400,1 -23521,1517936105365,1 -23522,1517936120723,1 -23523,1517936132821,1 -23524,1517936144323,1 -23525,1517936155615,1 -23526,1517936167451,1 -23527,1517936179026,1 -23528,1517936191129,1 -23529,1517936202798,1 -23530,1517936214961,1 -23531,1517936225664,1 -23532,1517936237662,1 -23533,1517936249410,1 -23534,1517936266395,1 -23535,1517936278168,1 -23536,1517936289883,1 -23537,1517936301170,1 -23538,1517936312918,1 -23539,1517936329954,1 -23540,1517936342190,1 -23541,1517936353915,1 -23542,1517936365762,1 -23543,1517936382382,1 -23544,1517936393839,1 -23545,1517936405826,1 -23546,1517936416835,1 -23547,1517936428505,1 -23548,1517936440595,1 -23549,1517936452607,1 -23550,1517936464008,1 -23551,1517936480238,1 -23552,1517936492152,1 -23553,1517936503751,1 -23554,1517936515478,1 -23555,1517936531193,1 -23556,1517936547612,1 -23557,1517936558991,1 -23558,1517936575417,1 -23559,1517936587299,1 -23560,1517936604272,1 -23561,1517936616104,1 -23562,1517936627727,1 -23563,1517936638685,1 -23564,1517936650125,1 -23565,1517936661747,1 -23566,1517936679031,1 -23567,1517936698636,1 -23568,1517936715410,1 -23569,1517936726767,1 -23570,1517936743247,1 -23571,1517936760453,1 -23572,1517936777245,1 -23573,1517936789593,1 -23574,1517936801250,1 -23575,1517936821840,1 -23576,1517936838082,1 -23577,1517936848993,1 -23578,1517936865600,1 -23579,1517936876417,1 -23580,1517936892600,1 -23581,1517936903881,1 -23582,1517936915594,1 -23583,1517936926610,1 -23584,1517936938689,1 -23585,1517936950389,1 -23586,1517936961866,1 -23587,1517936973783,1 -23588,1517936984801,1 -23589,1517936996683,1 -23590,1517937012959,1 -23591,1517937024042,1 -23592,1517937040197,1 -23593,1517937051763,2 -23594,1517937063733,2 -23595,1517937075177,2 -23596,1517937086587,3 -23597,1517937107708,3 -23598,1517937124035,3 -23599,1517937144029,4 -23600,1517937173675,4 -23601,1517937208166,4 -23602,1517937223202,5 -23603,1517937235011,5 -23604,1517937269509,6 -23605,1517937281382,6 -23606,1517937292606,7 -23607,1517937339043,9 -23608,1517937360202,9 -23609,1517937371662,10 -23610,1517937447778,13 -23611,1517937514457,13 -23612,1517937658048,13 -23613,1517937898557,13 -23614,1517938036361,12 -23615,1517938080427,12 -23616,1517938166884,13 -23617,1517938244696,12 -23618,1517938286798,12 -23619,1517938335792,13 -23620,1517938371044,13 -23621,1517938455050,14 -23622,1517938571356,13 -23623,1517938697583,14 -23624,1517938825032,13 -23625,1517938900140,14 -23626,1517938972424,14 -23627,1517939026969,13 -23628,1517939143681,13 -23629,1517939254739,13 -23630,1517939341358,14 -23631,1517939352357,14 -23632,1517939396390,16 -23633,1517939448130,17 -23634,1517939531902,18 -23635,1517939590395,17 -23636,1517939639538,17 -23637,1517939712119,18 -23638,1517939804497,18 -23639,1517939927098,18 -23640,1517940045790,18 -23641,1517940113405,18 -23642,1517940301419,18 -23643,1517940627131,18 -23644,1517940808687,17 -23645,1517940853667,16 -23646,1517940917256,17 -23647,1517940991058,18 -23648,1517941035305,17 -23649,1517941056860,18 -23650,1517941068477,19 -23651,1517941192992,23 -23652,1517941257576,22 -23653,1517941326635,22 -23654,1517941404287,23 -23655,1517941472944,23 -23656,1517941527189,23 -23657,1517941548201,23 -23658,1517941780285,25 -23659,1517942017991,25 -23660,1517942048643,25 -23661,1517942112771,26 -23662,1517942286585,26 -23663,1517942485759,25 -23664,1517942581255,25 -23665,1517942611008,25 -23666,1517942637044,26 -23667,1517942668126,28 -23668,1517942917499,29 -23669,1517943238868,28 -23670,1517943336333,28 -23671,1517943347798,27 -23672,1517943564326,32 -23673,1517943668123,32 -23674,1517943712178,32 -23675,1517943809164,33 -23676,1517943984570,32 -23677,1517944191063,31 -23678,1517944337272,31 -23679,1517944371915,31 -23680,1517944449290,32 -23681,1517944691663,31 -23682,1517944884338,30 -23683,1517945122652,30 -23684,1517945432910,29 -23685,1517945728182,29 -23686,1517946065118,28 -23687,1517946240011,27 -23688,1517946306827,26 -23689,1517946463624,26 -23690,1517946705080,25 -23691,1517946820653,25 -23692,1517946911466,24 -23693,1517947029337,23 -23694,1517947139909,23 -23695,1517947197807,22 -23696,1517947242283,23 -23697,1517947258032,23 -23698,1517947298384,25 -23699,1517947332908,26 -23700,1517947530141,27 -23701,1517947875246,26 -23702,1517948039723,25 -23703,1517948227533,24 -23704,1517948314834,25 -23705,1517948377564,23 -23706,1517948468434,24 -23707,1517948706412,24 -23708,1517948911532,24 -23709,1517949013234,23 -23710,1517949162989,24 -23711,1517949279272,22 -23712,1517949342969,23 -23713,1517949421322,22 -23714,1517949591330,22 -23715,1517949753744,20 -23716,1517949820757,20 -23717,1517950032167,20 -23718,1517950262957,19 -23719,1517950423504,19 -23720,1517950596198,18 -23721,1517950674463,18 -23722,1517950704719,17 -23723,1517950720325,17 -23724,1517950736876,19 -23725,1517950753904,20 -23726,1517950773846,22 -23727,1517950938444,23 -23728,1517951117206,22 -23729,1517951170709,22 -23730,1517951210545,22 -23731,1517951358951,22 -23732,1517951573832,22 -23733,1517951662245,22 -23734,1517951702789,21 -23735,1517951871224,22 -23736,1517952053647,21 -23737,1517952162256,20 -23738,1517952321428,20 -23739,1517952505017,18 -23740,1517952629730,18 -23741,1517952684311,17 -23742,1517952728178,16 -23743,1517952785850,17 -23744,1517952939428,16 -23745,1517953106676,15 -23746,1517953164626,15 -23747,1517953199173,13 -23748,1517953287280,13 -23749,1517953431283,13 -23750,1517953631501,13 -23751,1517953783069,14 -23752,1517953858785,13 -23753,1517953940846,13 -23754,1517953997391,12 -23755,1517954055402,12 -23756,1517954091568,12 -23757,1517954117850,12 -23758,1517954134290,13 -23759,1517954202609,13 -23760,1517954456195,13 -23761,1517954651432,13 -23762,1517954704063,13 -23763,1517954744551,13 -23764,1517954755916,12 -23765,1517954810392,13 -23766,1517954901919,14 -23767,1517955089823,14 -23768,1517955223028,14 -23769,1517955304963,14 -23770,1517955431429,14 -23771,1517955593530,13 -23772,1517955699400,14 -23773,1517955908321,14 -23774,1517956054847,14 -23775,1517956102642,14 -23776,1517956147304,14 -23777,1517956191764,14 -23778,1517956321705,14 -23779,1517956444611,13 -23780,1517956466062,13 -23781,1517956593726,14 -23782,1517956684508,14 -23783,1517956762365,14 -23784,1517956811694,12 -23785,1517956850205,13 -23786,1517956903663,13 -23787,1517956952885,12 -23788,1517957007299,12 -23789,1517957103647,12 -23790,1517957222318,11 -23791,1517957288509,11 -23792,1517957331794,10 -23793,1517957381927,10 -23794,1517957427933,10 -23795,1517957532730,10 -23796,1517957642942,9 -23797,1517957672399,10 -23798,1517957742869,11 -23799,1517957795323,10 -23800,1517957825141,12 -23801,1517957837208,12 -23802,1517957921581,13 -23803,1517958071588,13 -23804,1517958216579,12 -23805,1517958246207,11 -23806,1517958262853,12 -23807,1517958283643,14 -23808,1517958342193,14 -23809,1517958420243,13 -23810,1517958456096,14 -23811,1517958477158,13 -23812,1517958492475,15 -23813,1517958533097,16 -23814,1517958642118,16 -23815,1517958746374,16 -23816,1517958902670,15 -23817,1517959064227,15 -23818,1517959104249,14 -23819,1517959145226,14 -23820,1517959233025,14 -23821,1517959291991,13 -23822,1517959313602,13 -23823,1517959376045,14 -23824,1517959438981,15 -23825,1517959502288,16 -23826,1517959538814,17 -23827,1517959661773,19 -23828,1517959777069,18 -23829,1517959863243,18 -23830,1517959942838,18 -23831,1517960024247,18 -23832,1517960136629,18 -23833,1517960235457,18 -23834,1517960270486,17 -23835,1517960327989,19 -23836,1517960386258,18 -23837,1517960450622,18 -23838,1517960472043,18 -23839,1517960693414,20 -23840,1517960910172,19 -23841,1517961032644,18 -23842,1517961062740,18 -23843,1517961152928,19 -23844,1517961257119,19 -23845,1517961282637,18 -23846,1517961437915,19 -23847,1517961526591,19 -23848,1517961593848,19 -23849,1517961742958,19 -23850,1517961856502,18 -23851,1517961910289,18 -23852,1517961963422,18 -23853,1517962056664,18 -23854,1517962161752,17 -23855,1517962197684,17 -23856,1517962223385,18 -23857,1517962254023,19 -23858,1517962302767,19 -23859,1517962421823,21 -23860,1517962530515,20 -23861,1517962602784,20 -23862,1517962676383,20 -23863,1517962743106,20 -23864,1517962945027,19 -23865,1517963163410,20 -23866,1517963323178,20 -23867,1517963445823,19 -23868,1517963472868,19 -23869,1517963585579,19 -23870,1517963656587,19 -23871,1517963766613,18 -23872,1517963874374,18 -23873,1517963909564,18 -23874,1517963944584,18 -23875,1517963998627,18 -23876,1517964038858,18 -23877,1517964102193,19 -23878,1517964177204,19 -23879,1517964215618,19 -23880,1517964260880,19 -23881,1517964337973,20 -23882,1517964391137,19 -23883,1517964426647,19 -23884,1517964525980,19 -23885,1517964621067,20 -23886,1517964651793,19 -23887,1517964700472,20 -23888,1517964744421,20 -23889,1517964779129,20 -23890,1517964961575,21 -23891,1517965113639,20 -23892,1517965230132,20 -23893,1517965379161,19 -23894,1517965476310,19 -23895,1517965530565,18 -23896,1517965583879,18 -23897,1517965660089,18 -23898,1517965737229,17 -23899,1517965867385,17 -23900,1517966028890,16 -23901,1517966134826,16 -23902,1517966207667,17 -23903,1517966233560,16 -23904,1517966321549,17 -23905,1517966337617,16 -23906,1517966372566,18 -23907,1517966454342,19 -23908,1517966554751,19 -23909,1517966623120,18 -23910,1517966710336,18 -23911,1517966829449,18 -23912,1517966943649,18 -23913,1517967016642,19 -23914,1517967057422,19 -23915,1517967103057,19 -23916,1517967124738,19 -23917,1517967210665,20 -23918,1517967291853,20 -23919,1517967384666,20 -23920,1517967420631,20 -23921,1517967497791,20 -23922,1517967533572,19 -23923,1517967612130,20 -23924,1517967712465,20 -23925,1517967847309,19 -23926,1517967974293,20 -23927,1517968047248,19 -23928,1517968248023,19 -23929,1517968421716,18 -23930,1517968456388,18 -23931,1517968472776,18 -23932,1517968575314,20 -23933,1517968726977,19 -23934,1517968878672,19 -23935,1517968969925,19 -23936,1517969000275,19 -23937,1517969054154,19 -23938,1517969099270,19 -23939,1517969114959,20 -23940,1517969126351,22 -23941,1517969217538,26 -23942,1517969329286,26 -23943,1517969424502,26 -23944,1517969529400,25 -23945,1517969629901,25 -23946,1517969763589,24 -23947,1517969950571,25 -23948,1517970070832,24 -23949,1517970147506,23 -23950,1517970271213,22 -23951,1517970395437,22 -23952,1517970465266,21 -23953,1517970506600,21 -23954,1517970545639,22 -23955,1517970586782,22 -23956,1517970631522,22 -23957,1517970835826,23 -23958,1517971113171,23 -23959,1517971238322,23 -23960,1517971273607,22 -23961,1517971318764,23 -23962,1517971364006,23 -23963,1517971476898,23 -23964,1517971585676,24 -23965,1517971617191,22 -23966,1517971642565,23 -23967,1517971767263,24 -23968,1517971888355,23 -23969,1517971909114,23 -23970,1517972004865,25 -23971,1517972141449,25 -23972,1517972186203,24 -23973,1517972245032,25 -23974,1517972331602,25 -23975,1517972443060,25 -23976,1517972682689,24 -23977,1517972921115,23 -23978,1517973007906,23 -23979,1517973109237,23 -23980,1517973391447,23 -23981,1517973611088,22 -23982,1517973659894,21 -23983,1517973699150,22 -23984,1517973950474,23 -23985,1517974286390,21 -23986,1517974465062,21 -23987,1517974546925,20 -23988,1517974712111,20 -23989,1517974816877,20 -23990,1517975003527,20 -23991,1517975163297,19 -23992,1517975193524,18 -23993,1517975270747,19 -23994,1517975494821,19 -23995,1517975721156,18 -23996,1517975813044,16 -23997,1517975919965,17 -23998,1517975992675,16 -23999,1517976023914,16 -24000,1517976197497,16 -24001,1517976340177,15 -24002,1517976397114,15 -24003,1517976464953,14 -24004,1517976523402,13 -24005,1517976563193,14 -24006,1517976608811,14 -24007,1517976669545,15 -24008,1517976764667,14 -24009,1517976914203,14 -24010,1517977208729,13 -24011,1517977432273,12 -24012,1517977540991,11 -24013,1517977711045,10 -24014,1517977799646,10 -24015,1517977908050,10 -24016,1517978032624,9 -24017,1517978133511,10 -24018,1517978256318,9 -24019,1517978314037,8 -24020,1517978366939,8 -24021,1517978429569,8 -24022,1517978474386,7 -24023,1517978500468,7 -24024,1517978543341,8 -24025,1517978578067,7 -24026,1517978603631,7 -24027,1517978619835,6 -24028,1517978645333,7 -24029,1517978684606,7 -24030,1517978710338,6 -24031,1517978764542,6 -24032,1517978804025,7 -24033,1517978819556,6 -24034,1517978835881,6 -24035,1517978885106,6 -24036,1517978947392,6 -24037,1517978972907,5 -24038,1517979041287,5 -24039,1517979096240,5 -24040,1517979141743,6 -24041,1517979167598,8 -24042,1517979206461,8 -24043,1517979240431,8 -24044,1517979263142,8 -24045,1517979275164,9 -24046,1517979296687,9 -24047,1517979318262,10 -24048,1517979364159,11 -24049,1517979405117,10 -24050,1517979478585,10 -24051,1517979583517,10 -24052,1517979648739,10 -24053,1517979679653,9 -24054,1517979714873,10 -24055,1517979731077,10 -24056,1517979806536,11 -24057,1517979869215,11 -24058,1517979952575,11 -24059,1517979996521,10 -24060,1517980050369,11 -24061,1517980099579,10 -24062,1517980139276,11 -24063,1517980169388,11 -24064,1517980190425,11 -24065,1517980207558,13 -24066,1517980248123,14 -24067,1517980328357,15 -24068,1517980396824,15 -24069,1517980441270,15 -24070,1517980477509,16 -24071,1517980499618,17 -24072,1517980568158,18 -24073,1517980635890,18 -24074,1517980730137,18 -24075,1517980840252,19 -24076,1517980873712,19 -24077,1517980894150,19 -24078,1517980956635,21 -24079,1517981052678,21 -24080,1517981140386,21 -24081,1517981194758,21 -24082,1517981211493,21 -24083,1517981615148,23 -24084,1517982033364,23 -24085,1517982069512,22 -24086,1517982197961,24 -24087,1517982356170,23 -24088,1517982514161,22 -24089,1517982673218,22 -24090,1517982992718,22 -24091,1517983350355,21 -24092,1517983550438,20 -24093,1517983675172,20 -24094,1517983710168,21 -24095,1517983763877,21 -24096,1517983803538,21 -24097,1517983835046,22 -24098,1517983851839,23 -24099,1517984341277,25 -24100,1517984658860,25 -24101,1517984724235,24 -24102,1517984777855,25 -24103,1517984921132,25 -24104,1517985058658,25 -24105,1517985180857,24 -24106,1517985307503,23 -24107,1517985425266,24 -24108,1517985507941,23 -24109,1517985555104,23 -24110,1517985718539,24 -24111,1517985904078,23 -24112,1517986116509,22 -24113,1517986453870,21 -24114,1517986668238,21 -24115,1517986707169,20 -24116,1517986781496,21 -24117,1517986894108,20 -24118,1517987063084,19 -24119,1517987226017,19 -24120,1517987271778,18 -24121,1517987384673,19 -24122,1517987453453,18 -24123,1517987479094,18 -24124,1517987542642,19 -24125,1517987606633,19 -24126,1517987657127,18 -24127,1517987733425,19 -24128,1517987871314,19 -24129,1517988064667,18 -24130,1517988506570,17 -24131,1517988845509,16 -24132,1517988866556,16 -24133,1517988888176,17 -24134,1517988941582,18 -24135,1517988996514,19 -24136,1517989021613,18 -24137,1517989104215,19 -24138,1517989308243,19 -24139,1517989471405,18 -24140,1517989501540,17 -24141,1517989591484,17 -24142,1517989693329,17 -24143,1517989735348,16 -24144,1517989775161,17 -24145,1517989833782,18 -24146,1517989882801,17 -24147,1517989993701,18 -24148,1517990104936,18 -24149,1517990122549,17 -24150,1517990133417,18 -24151,1517990146397,22 -24152,1517990779213,24 -24153,1517991477701,23 -24154,1517991586497,23 -24155,1517991743697,22 -24156,1517991878636,22 -24157,1517991932447,21 -24158,1517992034652,21 -24159,1517992113773,21 -24160,1517992191568,21 -24161,1517992264555,20 -24162,1517992403074,19 -24163,1517992538268,19 -24164,1517992553920,19 -24165,1517992584539,21 -24166,1517992668647,22 -24167,1517992778187,22 -24168,1517992826783,22 -24169,1517992924764,22 -24170,1517993034033,22 -24171,1517993073629,22 -24172,1517993100358,22 -24173,1517993126782,24 -24174,1517993181475,25 -24175,1517993244804,25 -24176,1517993326814,24 -24177,1517993394604,25 -24178,1517993606840,25 -24179,1517993753122,25 -24180,1517993792921,24 -24181,1517993828504,25 -24182,1517993857991,26 -24183,1517993912069,29 -24184,1517993952087,29 -24185,1517994029108,29 -24186,1517994059814,29 -24187,1517994094239,31 -24188,1517994123506,31 -24189,1517994225539,33 -24190,1517994342281,33 -24191,1517994502791,32 -24192,1517994691810,31 -24193,1517994759302,30 -24194,1517994801872,30 -24195,1517994859564,31 -24196,1517995073634,32 -24197,1517995276495,31 -24198,1517995374334,30 -24199,1517995635891,31 -24200,1517996039645,31 -24201,1517996352486,30 -24202,1517996469210,29 -24203,1517996580543,29 -24204,1517996809724,28 -24205,1517997040350,27 -24206,1517997145080,27 -24207,1517997216003,26 -24208,1517997312275,26 -24209,1517997498673,25 -24210,1517997659244,25 -24211,1517997700189,24 -24212,1517997791312,24 -24213,1517997937030,24 -24214,1517998158086,23 -24215,1517998389977,21 -24216,1517998476059,22 -24217,1517998575958,21 -24218,1517998723391,21 -24219,1517998812781,20 -24220,1517998885310,19 -24221,1517998934266,19 -24222,1517999030430,19 -24223,1517999113331,18 -24224,1517999166571,18 -24225,1517999252155,18 -24226,1517999319581,17 -24227,1517999346052,17 -24228,1517999504448,17 -24229,1517999667368,17 -24230,1517999744184,16 -24231,1517999955698,15 -24232,1518000106906,13 -24233,1518000165108,14 -24234,1518000214179,14 -24235,1518000279936,14 -24236,1518000408939,13 -24237,1518000499368,13 -24238,1518000704147,13 -24239,1518000907344,11 -24240,1518000924364,10 -24241,1518000968248,11 -24242,1518001031649,11 -24243,1518001099102,10 -24244,1518001128978,9 -24245,1518001202280,10 -24246,1518001331420,9 -24247,1518001419675,8 -24248,1518001454503,7 -24249,1518001483924,7 -24250,1518001537764,7 -24251,1518001591597,9 -24252,1518001641277,10 -24253,1518001685661,10 -24254,1518001707083,9 -24255,1518001752131,9 -24256,1518001835823,8 -24257,1518001908179,8 -24258,1518001967901,7 -24259,1518002013187,6 -24260,1518002030648,6 -24261,1518002042380,7 -24262,1518002077470,7 -24263,1518002112994,7 -24264,1518002134222,6 -24265,1518002150651,7 -24266,1518002180547,8 -24267,1518002214965,8 -24268,1518002264160,8 -24269,1518002303568,7 -24270,1518002339372,6 -24271,1518002370091,7 -24272,1518002387325,7 -24273,1518002423361,8 -24274,1518002464305,8 -24275,1518002499346,8 -24276,1518002574241,9 -24277,1518002639860,8 -24278,1518002670215,8 -24279,1518002700455,7 -24280,1518002727359,7 -24281,1518002753650,8 -24282,1518002794331,9 -24283,1518002867902,9 -24284,1518002929886,8 -24285,1518002965094,9 -24286,1518002986208,9 -24287,1518003003415,11 -24288,1518003024034,12 -24289,1518003075535,14 -24290,1518003120629,14 -24291,1518003151086,15 -24292,1518003205913,15 -24293,1518003297456,15 -24294,1518003399619,15 -24295,1518003454324,15 -24296,1518003489096,16 -24297,1518003610219,16 -24298,1518003747404,16 -24299,1518003823473,15 -24300,1518003873318,15 -24301,1518003937064,15 -24302,1518004018602,16 -24303,1518004053010,15 -24304,1518004103141,16 -24305,1518004284897,16 -24306,1518004464308,15 -24307,1518004503229,15 -24308,1518004581056,16 -24309,1518004649053,16 -24310,1518004676571,15 -24311,1518004759139,17 -24312,1518004860820,16 -24313,1518004938394,16 -24314,1518005105538,16 -24315,1518005239643,15 -24316,1518005293156,15 -24317,1518005366912,15 -24318,1518005473751,15 -24319,1518005561639,15 -24320,1518005586798,15 -24321,1518005622319,15 -24322,1518005668044,17 -24323,1518005711981,16 -24324,1518005752128,16 -24325,1518005773056,17 -24326,1518005807805,19 -24327,1518005843551,19 -24328,1518005897087,21 -24329,1518005967592,20 -24330,1518006096255,21 -24331,1518006225381,20 -24332,1518006259968,19 -24333,1518006332201,20 -24334,1518006614031,20 -24335,1518006849281,20 -24336,1518006912504,19 -24337,1518007023675,19 -24338,1518007091537,19 -24339,1518007116654,18 -24340,1518007155552,20 -24341,1518007344366,20 -24342,1518007530810,20 -24343,1518007610035,20 -24344,1518007706114,19 -24345,1518007765230,19 -24346,1518007823761,19 -24347,1518007901234,19 -24348,1518008033851,19 -24349,1518008167754,18 -24350,1518008231111,18 -24351,1518008365991,18 -24352,1518008500695,18 -24353,1518008537083,18 -24354,1518008580099,18 -24355,1518008657908,18 -24356,1518008745025,18 -24357,1518008846462,17 -24358,1518008913452,17 -24359,1518008952627,17 -24360,1518008992558,17 -24361,1518009069944,18 -24362,1518009188468,18 -24363,1518009481638,17 -24364,1518009725948,17 -24365,1518009797607,16 -24366,1518009874361,17 -24367,1518009982585,17 -24368,1518010054592,16 -24369,1518010094936,16 -24370,1518010106911,15 -24371,1518010223988,18 -24372,1518010310760,18 -24373,1518010418600,18 -24374,1518010488057,18 -24375,1518010504634,17 -24376,1518010515821,19 -24377,1518010604149,22 -24378,1518010755598,21 -24379,1518010833449,21 -24380,1518010906297,21 -24381,1518011123174,21 -24382,1518011361491,21 -24383,1518011483613,20 -24384,1518011652694,19 -24385,1518011875178,18 -24386,1518012030496,18 -24387,1518012094991,17 -24388,1518012244108,18 -24389,1518012481183,18 -24390,1518012609948,17 -24391,1518012661583,17 -24392,1518012692792,17 -24393,1518012754814,18 -24394,1518012798685,17 -24395,1518012917978,18 -24396,1518013113590,17 -24397,1518013251041,17 -24398,1518013290672,17 -24399,1518013395274,17 -24400,1518013491604,17 -24401,1518013607644,16 -24402,1518013654498,15 -24403,1518013739130,16 -24404,1518013778602,16 -24405,1518013845738,16 -24406,1518013950479,15 -24407,1518014050250,15 -24408,1518014137203,15 -24409,1518014208646,14 -24410,1518014247865,14 -24411,1518014279046,15 -24412,1518014306270,15 -24413,1518014337700,15 -24414,1518014453817,16 -24415,1518014614032,16 -24416,1518014735092,14 -24417,1518014802608,14 -24418,1518014819023,14 -24419,1518014838750,15 -24420,1518014853899,16 -24421,1518014912696,19 -24422,1518014967631,18 -24423,1518015151700,18 -24424,1518015334101,18 -24425,1518015467566,18 -24426,1518015634619,18 -24427,1518015718701,18 -24428,1518015839272,18 -24429,1518015982816,17 -24430,1518016049766,17 -24431,1518016093977,17 -24432,1518016119917,17 -24433,1518016188488,18 -24434,1518016291350,18 -24435,1518016388202,18 -24436,1518016437172,17 -24437,1518016610728,17 -24438,1518016767645,17 -24439,1518016784313,16 -24440,1518016833710,18 -24441,1518016967851,19 -24442,1518017065685,18 -24443,1518017086759,18 -24444,1518017126534,19 -24445,1518017139218,19 -24446,1518017160053,23 -24447,1518017232935,24 -24448,1518017303322,24 -24449,1518017441592,24 -24450,1518017593341,24 -24451,1518017647266,23 -24452,1518017775776,23 -24453,1518017917142,23 -24454,1518018042140,22 -24455,1518018158945,22 -24456,1518018217172,21 -24457,1518018252171,21 -24458,1518018403919,22 -24459,1518018619430,22 -24460,1518018709758,21 -24461,1518018813576,22 -24462,1518018938901,21 -24463,1518018978947,20 -24464,1518019060527,20 -24465,1518019141553,20 -24466,1518019265777,19 -24467,1518019413291,19 -24468,1518019500576,18 -24469,1518019575185,18 -24470,1518019719787,18 -24471,1518019906189,18 -24472,1518019969313,18 -24473,1518020033821,18 -24474,1518020068235,18 -24475,1518020141591,18 -24476,1518020229252,19 -24477,1518020335159,21 -24478,1518020385642,19 -24479,1518020460259,20 -24480,1518020529888,20 -24481,1518020558679,19 -24482,1518020574517,21 -24483,1518020721544,23 -24484,1518020859973,22 -24485,1518021036835,21 -24486,1518021305123,21 -24487,1518021425884,20 -24488,1518021469514,20 -24489,1518021499671,20 -24490,1518021651396,20 -24491,1518021700195,19 -24492,1518021850444,19 -24493,1518021976392,19 -24494,1518022048456,19 -24495,1518022116467,19 -24496,1518022252018,19 -24497,1518022381801,18 -24498,1518022477101,17 -24499,1518022573448,18 -24500,1518022612756,16 -24501,1518022676645,17 -24502,1518022701959,16 -24503,1518022787632,17 -24504,1518022878809,17 -24505,1518023016847,16 -24506,1518023158636,16 -24507,1518023203973,16 -24508,1518023254283,16 -24509,1518023322670,15 -24510,1518023395568,15 -24511,1518023425764,14 -24512,1518023525182,15 -24513,1518023661301,15 -24514,1518023734032,15 -24515,1518023797045,14 -24516,1518023901730,13 -24517,1518023979552,13 -24518,1518024005692,12 -24519,1518024022386,13 -24520,1518024048510,15 -24521,1518024135292,17 -24522,1518024331152,17 -24523,1518024477902,17 -24524,1518024573897,16 -24525,1518024682696,15 -24526,1518024768772,14 -24527,1518024827563,13 -24528,1518024852058,13 -24529,1518025003109,14 -24530,1518025181950,13 -24531,1518025225757,12 -24532,1518025358070,13 -24533,1518025516983,12 -24534,1518025597990,12 -24535,1518025688277,12 -24536,1518025816190,11 -24537,1518025889387,10 -24538,1518025915314,10 -24539,1518025943886,9 -24540,1518025993001,10 -24541,1518026032291,11 -24542,1518026063151,10 -24543,1518026172022,10 -24544,1518026289340,10 -24545,1518026406878,10 -24546,1518026495209,12 -24547,1518026613406,12 -24548,1518026707780,12 -24549,1518026732599,12 -24550,1518026762596,13 -24551,1518026858288,13 -24552,1518026973147,12 -24553,1518027075616,12 -24554,1518027142444,11 -24555,1518027191540,11 -24556,1518027230661,11 -24557,1518027251961,12 -24558,1518027263691,12 -24559,1518027327039,14 -24560,1518027357180,14 -24561,1518027468019,14 -24562,1518027598075,14 -24563,1518027638278,14 -24564,1518027654132,14 -24565,1518027689283,16 -24566,1518027723693,15 -24567,1518027815490,16 -24568,1518027921318,16 -24569,1518028111745,15 -24570,1518028292735,15 -24571,1518028308375,15 -24572,1518028334110,16 -24573,1518028368936,16 -24574,1518028384863,17 -24575,1518028470955,19 -24576,1518028568005,19 -24577,1518028617209,19 -24578,1518028857661,19 -24579,1518029074073,19 -24580,1518029113448,18 -24581,1518029179379,19 -24582,1518029225091,19 -24583,1518029240806,20 -24584,1518029256597,23 -24585,1518029324822,25 -24586,1518029467883,25 -24587,1518029576696,25 -24588,1518029621785,24 -24589,1518029661756,25 -24590,1518029831704,27 -24591,1518030002338,25 -24592,1518030032488,25 -24593,1518030080213,26 -24594,1518030379692,27 -24595,1518030745299,27 -24596,1518031114871,26 -24597,1518031396975,25 -24598,1518031455293,24 -24599,1518031514074,25 -24600,1518031544168,25 -24601,1518031575295,25 -24602,1518031624339,27 -24603,1518031724947,28 -24604,1518031801924,28 -24605,1518031846757,28 -24606,1518031899718,29 -24607,1518031958522,28 -24608,1518032198207,29 -24609,1518032509544,29 -24610,1518032635407,27 -24611,1518032984606,27 -24612,1518033339575,27 -24613,1518033378794,26 -24614,1518033431884,27 -24615,1518033592226,27 -24616,1518033723078,26 -24617,1518033860482,25 -24618,1518033996844,25 -24619,1518034221365,25 -24620,1518034463109,25 -24621,1518034639739,25 -24622,1518034692829,24 -24623,1518034741983,24 -24624,1518034782069,24 -24625,1518034811545,25 -24626,1518034859564,26 -24627,1518034969608,26 -24628,1518035150927,26 -24629,1518035312421,26 -24630,1518035405529,25 -24631,1518035541619,24 -24632,1518035653432,23 -24633,1518035688150,23 -24634,1518035774677,23 -24635,1518035869219,23 -24636,1518035951373,22 -24637,1518036015255,22 -24638,1518036045521,22 -24639,1518036159839,23 -24640,1518036282805,22 -24641,1518036313586,21 -24642,1518036372259,22 -24643,1518036426249,23 -24644,1518036581868,22 -24645,1518036649460,21 -24646,1518036693235,21 -24647,1518036815254,20 -24648,1518037033291,20 -24649,1518037163415,19 -24650,1518037204107,18 -24651,1518037234575,19 -24652,1518037269243,19 -24653,1518037341865,19 -24654,1518037461688,19 -24655,1518037564465,18 -24656,1518037603663,18 -24657,1518037689639,18 -24658,1518037795472,17 -24659,1518037917683,17 -24660,1518038237893,17 -24661,1518038468783,17 -24662,1518038594081,15 -24663,1518038671750,15 -24664,1518038788282,14 -24665,1518038856281,14 -24666,1518038882353,14 -24667,1518038903021,15 -24668,1518038970496,15 -24669,1518039025050,15 -24670,1518039035901,15 -24671,1518039076575,16 -24672,1518039097251,17 -24673,1518039180265,19 -24674,1518039304552,18 -24675,1518039418876,18 -24676,1518039509973,18 -24677,1518039610328,18 -24678,1518039696362,17 -24679,1518039771929,16 -24680,1518039865195,15 -24681,1518039973523,16 -24682,1518040166638,14 -24683,1518040363399,14 -24684,1518040493324,15 -24685,1518040625924,15 -24686,1518040711467,14 -24687,1518040808598,14 -24688,1518040970971,14 -24689,1518041164185,13 -24690,1518041256108,13 -24691,1518041276268,13 -24692,1518041301243,14 -24693,1518041321576,15 -24694,1518041355896,16 -24695,1518041482245,16 -24696,1518041585666,15 -24697,1518041648678,15 -24698,1518041734141,14 -24699,1518041817534,14 -24700,1518041879715,13 -24701,1518041932073,14 -24702,1518041971662,14 -24703,1518042156533,15 -24704,1518042236298,14 -24705,1518042374586,14 -24706,1518042484434,15 -24707,1518042535411,14 -24708,1518042575237,14 -24709,1518042604928,14 -24710,1518042661595,14 -24711,1518042756197,15 -24712,1518042808006,14 -24713,1518042846650,14 -24714,1518042890654,14 -24715,1518042920377,15 -24716,1518042990414,15 -24717,1518043127001,15 -24718,1518043254701,14 -24719,1518043333548,13 -24720,1518043388984,12 -24721,1518043412999,13 -24722,1518043488482,13 -24723,1518043591858,13 -24724,1518043704930,13 -24725,1518043784234,12 -24726,1518043815310,13 -24727,1518043848774,14 -24728,1518043877921,14 -24729,1518043889435,14 -24730,1518043976897,16 -24731,1518044147227,16 -24732,1518044322661,15 -24733,1518044372008,14 -24734,1518044420016,15 -24735,1518044457174,15 -24736,1518044521608,15 -24737,1518044653977,16 -24738,1518044755806,15 -24739,1518044780616,16 -24740,1518044820456,16 -24741,1518044845421,17 -24742,1518044874683,17 -24743,1518044899579,19 -24744,1518044992036,19 -24745,1518045072254,19 -24746,1518045171800,19 -24747,1518045215643,19 -24748,1518045244330,20 -24749,1518045255277,20 -24750,1518045294092,23 -24751,1518045337248,24 -24752,1518045397054,26 -24753,1518045481703,26 -24754,1518045577341,26 -24755,1518045648097,25 -24756,1518045659449,26 -24757,1518045894407,30 -24758,1518046166453,29 -24759,1518046318774,29 -24760,1518046338770,28 -24761,1518046540730,30 -24762,1518046703369,30 -24763,1518046820320,29 -24764,1518046854502,29 -24765,1518046979122,29 -24766,1518047164818,29 -24767,1518047254062,28 -24768,1518047472456,29 -24769,1518047739866,28 -24770,1518047823278,28 -24771,1518047920093,29 -24772,1518048043859,29 -24773,1518048167825,30 -24774,1518048256535,29 -24775,1518048502194,29 -24776,1518048817805,28 -24777,1518048971530,28 -24778,1518049066442,27 -24779,1518049105454,26 -24780,1518049117024,27 -24781,1518049224229,32 -24782,1518049446319,32 -24783,1518049584188,31 -24784,1518049801405,30 -24785,1518050164009,29 -24786,1518050504691,28 -24787,1518050639548,27 -24788,1518050692028,26 -24789,1518050707298,27 -24790,1518050792627,29 -24791,1518050849895,29 -24792,1518050989910,30 -24793,1518051181053,29 -24794,1518051356657,30 -24795,1518051508467,29 -24796,1518051650128,28 -24797,1518051795328,28 -24798,1518051973883,27 -24799,1518052278108,26 -24800,1518052487020,25 -24801,1518052566253,25 -24802,1518052642825,24 -24803,1518052667858,24 -24804,1518052778194,25 -24805,1518052896847,24 -24806,1518052931640,24 -24807,1518053020289,24 -24808,1518053139844,23 -24809,1518053226373,23 -24810,1518053287554,23 -24811,1518053345696,23 -24812,1518053408296,22 -24813,1518053441873,22 -24814,1518053452054,23 -24815,1518053636690,27 -24816,1518053725182,27 -24817,1518053836410,27 -24818,1518053976530,26 -24819,1518054046705,25 -24820,1518054103303,24 -24821,1518054183008,24 -24822,1518054325596,23 -24823,1518054510703,23 -24824,1518054622034,22 -24825,1518054646618,21 -24826,1518054675438,22 -24827,1518054722264,23 -24828,1518054786428,23 -24829,1518054875250,23 -24830,1518054936921,23 -24831,1518054966262,23 -24832,1518054996601,24 -24833,1518055008577,24 -24834,1518055043466,28 -24835,1518055073463,28 -24836,1518055262614,29 -24837,1518055477547,29 -24838,1518055529227,27 -24839,1518055568748,27 -24840,1518055633562,28 -24841,1518055689821,28 -24842,1518055839719,28 -24843,1518056012059,28 -24844,1518056092040,27 -24845,1518056315798,27 -24846,1518056604197,26 -24847,1518056769888,25 -24848,1518056884572,24 -24849,1518433319586,24 -24850,1518433375335,24 -24851,1518433398038,25 -24852,1518433437666,26 -24853,1518433468832,27 -24854,1518433505087,28 -24855,1518433554725,29 -24856,1518433601424,29 -24857,1518433647757,32 -24858,1518433748053,32 -24859,1518433765263,31 -24860,1518433825267,34 -24861,1518433874849,35 -24862,1518433887798,36 -24863,1518433919301,42 -24864,1518433971787,43 -24865,1518433994267,45 -24866,1518434060113,48 -24867,1518434106902,48 -24868,1518434208321,49 -24869,1518434277760,49 -24870,1518434310280,48 -24871,1518434322155,51 -24872,1518434347302,59 -24873,1518434444501,63 -24874,1518434474656,63 -24875,1518434540336,65 -24876,1518434892592,66 -24877,1518434912550,64 -24878,1518434959267,70 -24879,1518435566687,71 -24880,1518435611587,70 -24881,1518435727623,75 -24882,1518435826427,74 -24883,1518436003287,73 -24884,1518436357594,73 -24885,1518436853672,71 -24886,1518437082972,69 -24887,1518437163362,67 -24888,1518437223677,67 -24889,1518437368583,68 -24890,1518437404178,68 -24891,1518437603242,71 -24892,1518437716852,71 -24893,1518437852748,70 -24894,1518437863053,68 -24895,1518438091008,82 -24896,1518438490691,81 -24897,1518438648400,78 -24898,1518438736855,78 -24899,1518439212429,77 -24900,1518439516118,74 -24901,1518439662845,72 -24902,1518439706432,72 -24903,1518439987700,72 -24904,1518440039243,72 -24905,1518440290091,72 -24906,1518440379671,71 -24907,1518440652861,70 -24908,1518440713842,69 -24909,1518440783320,69 -24910,1518441335467,69 -24911,1518441553488,66 -24912,1518442058684,64 -24913,1518442105571,62 -24914,1518442422706,63 -24915,1518442616469,64 -24916,1518442662914,62 -24917,1518442894213,62 -24918,1518443111321,61 -24919,1518443337209,58 -24920,1518443650669,57 -24921,1518443785425,55 -24922,1518443981560,53 -24923,1518444039640,51 -24924,1518444078499,50 -24925,1518444183359,51 -24926,1518444336338,51 -24927,1518444398954,49 -24928,1518444442845,49 -24929,1518444679020,49 -24930,1518445019821,46 -24931,1518445081844,45 -24932,1518445134557,45 -24933,1518445146202,44 -24934,1518445297549,53 -24935,1518445502238,52 -24936,1518445515629,50 -24937,1518445587662,57 -24938,1518445687521,56 -24939,1518445742658,55 -24940,1518445984963,55 -24941,1518446219146,52 -24942,1518446374354,50 -24943,1518446432128,48 -24944,1518446473662,48 -24945,1518446647180,48 -24946,1518446724927,45 -24947,1518446827136,44 -24948,1518446918601,41 -24949,1518446981112,39 -24950,1518447245911,38 -24951,1518447338177,35 -24952,1518447527217,35 -24953,1518447592878,32 -24954,1518447657970,32 -24955,1518447726441,31 -24956,1518447770995,29 -24957,1518447889451,28 -24958,1518448033970,27 -24959,1518448099684,24 -24960,1518448141663,24 -24961,1518448193556,23 -24962,1518448332267,22 -24963,1518448413401,23 -24964,1518448473654,22 -24965,1518448547268,21 -24966,1518448583874,21 -24967,1518448649203,20 -24968,1518448714478,19 -24969,1518448757429,18 -24970,1518448804002,17 -24971,1518448900667,17 -24972,1518448934858,20 -24973,1518448995106,22 -24974,1518449044408,20 -24975,1518449122584,21 -24976,1518449198070,21 -24977,1518449221292,20 -24978,1518449260274,23 -24979,1518449336296,23 -24980,1518449454586,22 -24981,1518449478971,22 -24982,1518449550480,23 -24983,1518449586161,22 -24984,1518449639401,22 -24985,1518449706521,20 -24986,1518449744276,19 -24987,1518449782257,19 -24988,1518449806644,19 -24989,1518449822629,19 -24990,1518449877405,21 -24991,1518449905315,21 -24992,1518450045811,21 -24993,1518450110197,20 -24994,1518450136842,20 -24995,1518450172566,27 -24996,1518450301096,27 -24997,1518450450744,26 -24998,1518450636360,25 -24999,1518450671063,24 -25000,1518450756179,24 -25001,1518450782433,23 -25002,1518450814162,23 -25003,1518450893315,25 -25004,1518450977967,24 -25005,1518451072628,25 -25006,1518451154021,24 -25007,1518451203730,23 -25008,1518451373607,22 -25009,1518451484545,23 -25010,1518451513416,22 -25011,1518451610816,22 -25012,1518451652409,22 -25013,1518451670307,20 -25014,1518451793209,23 -25015,1518451864292,22 -25016,1518451905985,21 -25017,1518452075997,22 -25018,1518452147183,20 -25019,1518452254287,20 -25020,1518452287288,19 -25021,1518452323841,18 -25022,1518452333831,18 -25023,1518452419118,21 -25024,1518452497228,20 -25025,1518452542684,20 -25026,1518452608538,21 -25027,1518452619333,19 -25028,1518452693173,23 -25029,1518452808867,23 -25030,1518452877856,22 -25031,1518452896650,21 -25032,1518452973109,22 -25033,1518452993363,22 -25034,1518453005286,28 -25035,1518453081251,31 -25036,1518453120561,31 -25037,1518453221831,36 -25038,1518453256804,36 -25039,1518453563587,38 -25040,1518453694876,37 -25041,1518453830399,36 -25042,1518454190874,35 -25043,1518454232272,34 -25044,1518454290825,35 -25045,1518454355194,36 -25046,1518454525381,36 -25047,1518454576717,35 -25048,1518454674641,36 -25049,1518454743774,35 -25050,1518454864608,36 -25051,1518454923755,35 -25052,1518454992796,35 -25053,1518455079588,35 -25054,1518455205895,34 -25055,1518455282879,34 -25056,1518455359510,34 -25057,1518455524015,34 -25058,1518455554619,34 -25059,1518455610913,34 -25060,1518455649216,35 -25061,1518455814405,36 -25062,1518455958224,34 -25063,1518456055456,33 -25064,1518456090828,34 -25065,1518456141833,34 -25066,1518456195675,34 -25067,1518456295740,34 -25068,1518456427000,34 -25069,1518456532315,33 -25070,1518456606549,32 -25071,1518456644912,32 -25072,1518456752530,33 -25073,1518456790879,32 -25074,1518456823896,32 -25075,1518456916358,34 -25076,1518456995640,33 -25077,1518457073208,33 -25078,1518457134682,33 -25079,1518457152306,32 -25080,1518457193371,36 -25081,1518457285857,36 -25082,1518457364953,36 -25083,1518457462430,36 -25084,1518457477398,35 -25085,1518457613683,40 -25086,1518457633820,38 -25087,1518457703195,42 -25088,1518457805565,42 -25089,1518457869766,42 -25090,1518458186476,43 -25091,1518458245367,42 -25092,1518458319482,41 -25093,1518458427375,41 -25094,1518458509440,41 -25095,1518458591395,41 -25096,1518458789992,41 -25097,1518458867073,40 -25098,1518458881970,39 -25099,1518459129358,43 -25100,1518459156949,42 -25101,1518459174599,44 -25102,1518459274586,49 -25103,1518459317640,49 -25104,1518459422509,50 -25105,1518459545924,50 -25106,1518459659144,48 -25107,1518459725714,48 -25108,1518459848538,47 -25109,1518459876619,46 -25110,1518460004995,49 -25111,1518460264467,47 -25112,1518460341377,46 -25113,1518460384533,46 -25114,1518460443645,48 -25115,1518460502605,48 -25116,1518460553915,47 -25117,1518460785310,48 -25118,1518460969857,46 -25119,1518461299195,45 -25120,1518461506791,43 -25121,1518461570790,41 -25122,1518461585721,41 -25123,1518461845735,48 -25124,1518462059006,47 -25125,1518462161437,45 -25126,1518462194290,44 -25127,1518462312107,45 -25128,1518462414978,46 -25129,1518462516837,45 -25130,1518462814795,44 -25131,1518463037856,42 -25132,1518463280249,42 -25133,1518463398526,40 -25134,1518463603235,40 -25135,1518463646302,41 -25136,1518463787505,42 -25137,1518463884790,42 -25138,1518463918072,41 -25139,1518464038691,42 -25140,1518464155135,41 -25141,1518464265245,40 -25142,1518464367812,39 -25143,1518464413613,38 -25144,1518464542277,39 -25145,1518464557275,38 -25146,1518464636377,43 -25147,1518464754550,41 -25148,1518464862275,41 -25149,1518464964561,40 -25150,1518464997741,39 -25151,1518465272708,40 -25152,1518465447212,38 -25153,1518465554691,37 -25154,1518465623426,37 -25155,1518465905616,36 -25156,1518466366325,35 -25157,1518466404782,32 -25158,1518466589610,33 -25159,1518466676835,32 -25160,1518466841160,31 -25161,1518466951563,31 -25162,1518467078042,29 -25163,1518467190726,28 -25164,1518467205692,26 -25165,1518467300308,29 -25166,1518467343493,29 -25167,1518467466745,29 -25168,1518467489662,27 -25169,1518467757419,29 -25170,1518467836933,27 -25171,1518467875221,26 -25172,1518468122360,26 -25173,1518468163047,25 -25174,1518468185713,25 -25175,1518468244216,26 -25176,1518468336700,25 -25177,1518468379950,25 -25178,1518468481970,24 -25179,1518468538077,23 -25180,1518468568501,24 -25181,1518468591024,25 -25182,1518468652165,26 -25183,1518468695016,25 -25184,1518468840385,24 -25185,1518468899298,25 -25186,1518468980805,25 -25187,1518469037210,26 -25188,1518469054656,26 -25189,1518469305729,27 -25190,1518469325871,26 -25191,1518469425298,27 -25192,1518469476372,27 -25193,1518469537363,26 -25194,1518469685841,26 -25195,1518469698514,25 -25196,1518469846903,28 -25197,1518469918354,27 -25198,1518469966615,25 -25199,1518470117409,28 -25200,1518470296603,26 -25201,1518470399010,26 -25202,1518470565375,28 -25203,1518470626264,27 -25204,1518470656511,28 -25205,1518470704734,29 -25206,1518470750188,29 -25207,1518470796416,29 -25208,1518470842355,29 -25209,1518470859991,30 -25210,1518470928777,33 -25211,1518470979687,32 -25212,1518471040820,32 -25213,1518471178423,33 -25214,1518471244707,32 -25215,1518471295582,33 -25216,1518471336155,33 -25217,1518471522853,34 -25218,1518471635155,33 -25219,1518471783350,32 -25220,1518471865292,30 -25221,1518472016133,30 -25222,1518472028942,30 -25223,1518472153590,36 -25224,1518472232803,35 -25225,1518472378421,35 -25226,1518472675572,34 -25227,1518472708493,34 -25228,1518472893284,35 -25229,1518472990938,34 -25230,1518473134015,33 -25231,1518473243639,32 -25232,1518473383795,31 -25233,1518473457882,30 -25234,1518473539581,29 -25235,1518473611140,29 -25236,1518473618416,29 -25237,1518473800025,37 -25238,1518473955902,36 -25239,1518474006840,36 -25240,1518474078327,36 -25241,1518474121453,35 -25242,1518474424642,36 -25243,1518474529470,35 -25244,1518474633840,34 -25245,1518474697320,34 -25246,1518474796592,36 -25247,1518474865685,36 -25248,1518474934780,36 -25249,1518474995819,35 -25250,1518475144581,35 -25251,1518475236072,35 -25252,1518475307721,34 -25253,1518475358756,34 -25254,1518475404724,34 -25255,1518475519547,34 -25256,1518475645248,33 -25257,1518475786256,32 -25258,1518475895757,32 -25259,1518475913261,30 -25260,1518476005393,33 -25261,1518476089463,32 -25262,1518476099392,31 -25263,1518476135121,38 -25264,1518476258105,38 -25265,1518476447840,39 -25266,1518476594004,38 -25267,1518476681178,38 -25268,1518476791214,37 -25269,1518476827150,37 -25270,1518476965123,37 -25271,1518477028851,37 -25272,1518477095098,36 -25273,1518477299743,36 -25274,1518477317175,35 -25275,1518477488714,39 -25276,1518477526870,38 -25277,1518477567564,39 -25278,1518477703023,39 -25279,1518477905319,38 -25280,1518477974016,37 -25281,1518477988982,38 -25282,1518478062501,43 -25283,1518478288082,43 -25284,1518478384847,41 -25285,1518478541618,41 -25286,1518478684738,39 -25287,1518478781597,38 -25288,1518478827540,38 -25289,1518479014601,39 -25290,1518479055277,37 -25291,1518479193380,39 -25292,1518479300449,38 -25293,1518479376516,38 -25294,1518479414758,37 -25295,1518479442474,37 -25296,1518479605772,41 -25297,1518479687951,39 -25298,1518479728180,39 -25299,1518479804717,40 -25300,1518479974115,40 -25301,1518480050464,38 -25302,1518480096491,37 -25303,1518480216326,37 -25304,1518480231346,37 -25305,1518480509636,41 -25306,1518480552834,40 -25307,1518480750683,41 -25308,1518480791118,40 -25309,1518480816305,41 -25310,1518480913595,45 -25311,1518480987399,44 -25312,1518481171921,44 -25313,1518481322267,43 -25314,1518481478943,42 -25315,1518481524664,41 -25316,1518481621614,41 -25317,1518481741458,41 -25318,1518481945817,40 -25319,1518482037664,39 -25320,1518482153338,38 -25321,1518482237740,37 -25322,1518482301449,35 -25323,1518482444597,37 -25324,1518482472268,37 -25325,1518482505074,38 -25326,1518482673934,38 -25327,1518482794381,37 -25328,1518482832437,37 -25329,1518482993029,38 -25330,1518483173050,36 -25331,1518483244101,35 -25332,1518483404877,34 -25333,1518483481502,33 -25334,1518483612212,32 -25335,1518483795852,31 -25336,1518483908931,29 -25337,1518483990855,32 -25338,1518484080191,31 -25339,1518484338635,31 -25340,1518484399875,29 -25341,1518484424987,29 -25342,1518484511940,31 -25343,1518484562721,31 -25344,1518484606008,30 -25345,1518484664573,30 -25346,1518484756441,30 -25347,1518484807503,29 -25348,1518484877125,29 -25349,1518484948150,28 -25350,1518485021785,28 -25351,1518485137095,26 -25352,1518485323464,26 -25353,1518485399988,24 -25354,1518485422912,24 -25355,1518485535312,25 -25356,1518485615020,24 -25357,1518485678377,23 -25358,1518485790754,22 -25359,1518485859998,21 -25360,1518485948966,21 -25361,1518486054330,20 -25362,1518486084816,20 -25363,1518486225834,22 -25364,1518486271597,22 -25365,1518486381859,22 -25366,1518486435502,21 -25367,1518486479000,20 -25368,1518486514718,20 -25369,1518486534702,19 -25370,1518486588276,21 -25371,1518486639226,20 -25372,1518486718202,20 -25373,1518486735814,19 -25374,1518486812605,21 -25375,1518486858493,22 -25376,1518486970641,21 -25377,1518487006245,21 -25378,1518487087802,22 -25379,1518487151890,21 -25380,1518487184801,20 -25381,1518487220360,20 -25382,1518487266465,23 -25383,1518487338051,23 -25384,1518487445291,22 -25385,1518487514025,22 -25386,1518487611314,21 -25387,1518487639323,20 -25388,1518487736787,21 -25389,1518487790202,19 -25390,1518487841207,19 -25391,1518487917488,19 -25392,1518487939993,19 -25393,1518488091432,20 -25394,1518488131888,18 -25395,1518488174909,19 -25396,1518488212950,19 -25397,1518488272140,19 -25398,1518488302569,19 -25399,1518488463977,20 -25400,1518488494292,20 -25401,1518488547872,19 -25402,1518488573041,20 -25403,1518488588144,20 -25404,1518488603354,22 -25405,1518488620828,27 -25406,1518488707119,29 -25407,1518488899476,29 -25408,1518488914519,29 -25409,1518488973140,33 -25410,1518489124299,34 -25411,1518489277845,33 -25412,1518489303194,33 -25413,1518489394696,35 -25414,1518489571496,34 -25415,1518489738398,33 -25416,1518489781566,33 -25417,1518489812019,34 -25418,1518489898522,35 -25419,1518489992739,35 -25420,1518490033375,34 -25421,1518490117502,35 -25422,1518490132473,35 -25423,1518490229490,39 -25424,1518490275313,39 -25425,1518490367807,40 -25426,1518490524364,42 -25427,1518490603518,41 -25428,1518490734176,40 -25429,1518491044632,41 -25430,1518491281891,39 -25431,1518491412281,38 -25432,1518491481059,37 -25433,1518491529251,37 -25434,1518491610910,38 -25435,1518491682628,37 -25436,1518491704983,37 -25437,1518491840514,40 -25438,1518491888891,38 -25439,1518492042729,40 -25440,1518492201241,38 -25441,1518492277936,38 -25442,1518492382681,38 -25443,1518492551620,38 -25444,1518492602466,37 -25445,1518492678704,38 -25446,1518492791535,38 -25447,1518492845447,37 -25448,1518492947646,38 -25449,1518493106467,37 -25450,1518493124011,36 -25451,1518493233959,40 -25452,1518493264300,39 -25453,1518493351807,41 -25454,1518493371717,40 -25455,1518493428172,45 -25456,1518493613015,45 -25457,1518493627859,44 -25458,1518493686784,49 -25459,1518493750856,50 -25460,1518493794195,49 -25461,1518494016851,50 -25462,1518494160233,49 -25463,1518494224618,48 -25464,1518494344316,48 -25465,1518494359183,48 -25466,1518494520876,53 -25467,1518494658700,52 -25468,1518495132772,52 -25469,1518495311785,50 -25470,1518495324398,50 -25471,1518495352598,57 -25472,1518495498667,60 -25473,1518496037233,59 -25474,1518496390859,58 -25475,1518496523662,56 -25476,1518496676810,56 -25477,1518496755964,55 -25478,1518496875939,55 -25479,1518497188331,53 -25480,1518497347108,52 -25481,1518497388160,51 -25482,1518497593331,53 -25483,1518498085137,51 -25484,1518498334029,50 -25485,1518498405510,48 -25486,1518498671037,47 -25487,1518498865393,46 -25488,1518498903601,44 -25489,1518498980186,45 -25490,1518499023188,45 -25491,1518499207448,45 -25492,1518499276201,44 -25493,1518499464886,43 -25494,1518499664453,42 -25495,1518499948301,40 -25496,1518500053815,38 -25497,1518500127806,38 -25498,1518500155584,37 -25499,1518500252823,39 -25500,1518500306025,37 -25501,1518500341604,37 -25502,1518500553657,38 -25503,1518500643058,36 -25504,1518500732695,37 -25505,1518500778573,37 -25506,1518500965263,39 -25507,1518501085487,37 -25508,1518501151985,35 -25509,1518501174476,37 -25510,1518501276401,38 -25511,1518501352726,38 -25512,1518501560294,37 -25513,1518501603848,37 -25514,1518501680440,36 -25515,1518501748856,36 -25516,1518501869352,34 -25517,1518501902577,34 -25518,1518502017083,35 -25519,1518502042491,34 -25520,1518502108810,35 -25521,1518502406497,35 -25522,1518502478220,33 -25523,1518502521954,35 -25524,1518502595631,35 -25525,1518502670047,36 -25526,1518502758662,35 -25527,1518502773526,34 -25528,1518503034878,38 -25529,1518503103712,36 -25530,1518503157261,35 -25531,1518503328390,34 -25532,1518503510394,32 -25533,1518503573869,31 -25534,1518503714412,31 -25535,1518503739944,29 -25536,1518503770678,30 -25537,1518503832142,33 -25538,1518503937423,32 -25539,1518503996023,31 -25540,1518504008746,31 -25541,1518504139114,34 -25542,1518504320904,33 -25543,1518504373575,32 -25544,1518504637168,31 -25545,1518504734411,30 -25546,1518505378746,29 -25547,1518505413268,26 -25548,1518505465548,27 -25549,1518505512897,26 -25550,1518505606435,25 -25551,1518505890694,26 -25552,1518506049170,24 -25553,1518506073757,24 -25554,1518506124120,25 -25555,1518506149723,26 -25556,1518506253500,27 -25557,1518506374513,26 -25558,1518506426091,27 -25559,1518506548938,27 -25560,1518506560249,26 -25561,1518506634678,32 -25562,1518506674787,30 -25563,1518506712481,30 -25564,1518506809371,31 -25565,1518506860748,30 -25566,1518506885617,33 -25567,1518506933664,35 -25568,1518507248751,35 -25569,1518507340683,33 -25570,1518507454758,32 -25571,1518507536100,36 -25572,1518507693312,37 -25573,1518507706205,36 -25574,1518507788494,41 -25575,1518507928085,40 -25576,1518508050868,39 -25577,1518508059040,38 -25578,1518508104563,49 -25579,1518508197781,49 -25580,1518508677079,48 -25581,1518508923778,47 -25582,1518508973700,47 -25583,1518509012761,48 -25584,1518509069364,48 -25585,1518509135143,48 -25586,1518509210074,48 -25587,1518509370732,48 -25588,1518509451653,46 -25589,1518509564324,46 -25590,1518509742661,46 -25591,1518509761715,46 -25592,1518509933496,50 -25593,1518510032610,49 -25594,1518510196612,48 -25595,1518510351634,46 -25596,1518510442252,45 -25597,1518510539766,45 -25598,1518510877575,44 -25599,1518510993079,43 -25600,1518511128966,43 -25601,1518511152726,41 -25602,1518511230024,44 -25603,1518511322845,44 -25604,1518511348779,43 -25605,1518511452220,45 -25606,1518511548028,46 -25607,1518521641884,44 -25608,1518521705233,42 -25609,1518521771083,42 -25610,1518521981929,43 -25611,1518522124165,42 -25612,1518522135582,41 -25613,1518522438603,48 -25614,1518522567161,46 -25615,1518522650096,45 -25616,1518522666570,45 -25617,1518522759951,49 -25618,1518522860131,49 -25619,1518522965858,48 -25620,1518523056774,48 -25621,1518523240657,48 -25622,1518523532510,46 -25623,1518523865266,45 -25624,1518523887725,44 -25625,1518523968856,46 -25626,1518524037840,46 -25627,1518524168934,45 -25628,1518524459105,46 -25629,1518524555701,44 -25630,1518524756453,44 -25631,1518524877008,43 -25632,1518525000270,42 -25633,1518525101836,40 -25634,1518525206888,39 -25635,1518525488532,38 -25636,1518525678378,38 -25637,1518525822050,36 -25638,1518525961288,36 -25639,1518526033087,35 -25640,1518526116089,34 -25641,1518526178734,35 -25642,1518526304029,35 -25643,1518526358756,33 -25644,1518526454766,34 -25645,1518526488220,32 -25646,1518526508505,33 -25647,1518526549155,34 -25648,1518526560613,34 -25649,1518526724565,40 -25650,1518526807922,39 -25651,1518526960966,37 -25652,1518527120864,36 -25653,1518527400319,34 -25654,1518527564023,33 -25655,1518527613009,32 -25656,1518527668879,32 -25657,1518527740622,31 -25658,1518527783433,30 -25659,1518527826619,30 -25660,1518527889500,30 -25661,1518528070074,31 -25662,1518528130214,29 -25663,1518528343201,30 -25664,1518528384339,29 -25665,1518528509580,28 -25666,1518528583039,27 -25667,1518528648164,27 -25668,1518528687743,26 -25669,1518528786650,26 -25670,1518528803112,24 -25671,1518528868567,27 -25672,1518528959358,26 -25673,1518528975734,24 -25674,1518529026317,29 -25675,1518529155030,28 -25676,1518529171103,27 -25677,1518529510226,29 -25678,1518529560233,32 -25679,1518529614241,33 -25680,1518529767913,34 -25681,1518529881452,32 -25682,1518530102714,30 -25683,1518530205737,29 -25684,1518530228121,30 -25685,1518530289951,32 -25686,1518530344167,32 -25687,1518530403844,32 -25688,1518530452364,32 -25689,1518530535261,32 -25690,1518530606807,31 -25691,1518530656099,30 -25692,1518530692619,32 -25693,1518530925022,33 -25694,1518530999873,32 -25695,1518531165800,31 -25696,1518531254882,29 -25697,1518531278890,29 -25698,1518531485148,29 -25699,1518531534200,28 -25700,1518531625969,28 -25701,1518531661396,27 -25702,1518531872558,29 -25703,1518531956128,28 -25704,1518532114929,27 -25705,1518532213365,28 -25706,1518532299216,26 -25707,1518532327384,26 -25708,1518532418767,26 -25709,1518532464403,26 -25710,1518532550474,26 -25711,1518532647747,25 -25712,1518532815536,23 -25713,1518532852424,26 -25714,1518532990416,26 -25715,1518533038792,25 -25716,1518533139173,25 -25717,1518533228765,27 -25718,1518533246789,27 -25719,1518533330464,29 -25720,1518533559403,29 -25721,1518533655934,28 -25722,1518533708281,27 -25723,1518533828145,26 -25724,1518533869382,26 -25725,1518533922757,27 -25726,1518534027705,27 -25727,1518534152376,27 -25728,1518534234851,26 -25729,1518534380770,26 -25730,1518534414904,24 -25731,1518534446828,24 -25732,1518534498456,25 -25733,1518534544237,25 -25734,1518534625973,25 -25735,1518534679539,24 -25736,1518534752900,24 -25737,1518534843973,23 -25738,1518534858562,22 -25739,1518535028292,24 -25740,1518535036471,23 -25741,1518535050968,29 -25742,1518535107196,32 -25743,1518535172108,32 -25744,1518535365174,31 -25745,1518535392571,31 -25746,1518535469792,32 -25747,1518535660390,33 -25748,1518535806831,33 -25749,1518536044152,35 -25750,1518536334819,34 -25751,1518536433720,33 -25752,1518536460064,32 -25753,1518536583917,33 -25754,1518536614607,32 -25755,1518536705049,33 -25756,1518547955097,33 -25757,1518548048051,32 -25758,1518548099998,31 -25759,1518548224689,32 -25760,1518548368606,31 -25761,1518548425513,30 -25762,1518548587446,30 -25763,1518548640876,29 -25764,1518548795920,29 -25765,1518548862251,29 -25766,1518548991430,28 -25767,1518549029567,27 -25768,1518549177355,28 -25769,1518549295461,26 -25770,1518549414862,25 -25771,1518549559566,26 -25772,1518549612087,26 -25773,1518549649098,25 -25774,1518549664266,26 -25775,1518549762648,30 -25776,1518549858481,29 -25777,1518549948876,30 -25778,1518549981619,29 -25779,1518550006857,30 -25780,1518550125048,32 -25781,1518550198283,31 -25782,1518550465386,31 -25783,1518550597943,29 -25784,1518550622572,29 -25785,1518550707768,31 -25786,1518550780705,30 -25787,1518550941668,30 -25788,1518550997421,31 -25789,1518551081426,31 -25790,1518551113092,30 -25791,1518551243082,31 -25792,1518551300673,31 -25793,1518551337059,31 -25794,1518551419970,31 -25795,1518551493887,31 -25796,1518551812407,31 -25797,1518551888041,30 -25798,1518551948693,30 -25799,1518551996094,30 -25800,1518552171548,30 -25801,1518552199682,29 -25802,1518552420559,31 -25803,1518552483269,30 -25804,1518552531835,30 -25805,1518552657498,30 -25806,1518552741951,28 -25807,1518552851361,28 -25808,1518552940665,28 -25809,1518553060669,28 -25810,1518553134559,26 -25811,1518553143881,26 -25812,1518553226969,31 -25813,1518553337327,31 -25814,1518553413824,30 -25815,1518553510634,29 -25816,1518553607179,29 -25817,1518553670828,28 -25818,1518553792870,28 -25819,1518553856348,28 -25820,1518553895463,28 -25821,1518554023739,28 -25822,1518554066048,27 -25823,1518554272978,28 -25824,1518554284607,27 -25825,1518554324128,30 -25826,1518554407228,31 -25827,1518554418270,31 -25828,1518554497290,36 -25829,1518554539271,35 -25830,1518554563236,36 -25831,1518554874110,38 -25832,1518554923133,37 -25833,1518555014938,37 -25834,1518555111175,37 -25835,1518555192120,36 -25836,1518555313234,36 -25837,1518555465628,35 -25838,1518555726337,34 -25839,1518555961768,34 -25840,1518556043849,33 -25841,1518556087793,35 -25842,1518556116629,37 -25843,1518556264425,39 -25844,1518556287421,39 -25845,1518556418390,41 -25846,1518556542044,41 -25847,1518556625331,41 -25848,1518556705458,40 -25849,1518556800614,39 -25850,1518556990221,39 -25851,1518557226561,38 -25852,1518557265208,36 -25853,1518557328875,38 -25854,1518557568094,38 -25855,1518557791248,38 -25856,1518557881139,36 -25857,1518557995877,36 -25858,1518558050044,35 -25859,1518558131448,35 -25860,1518558298216,35 -25861,1518558382974,34 -25862,1518558530013,33 -25863,1518558670502,32 -25864,1518558722633,32 -25865,1518558842329,32 -25866,1518559034617,30 -25867,1518559089242,30 -25868,1518559321785,29 -25869,1518559336816,28 -25870,1518559405750,31 -25871,1518559417559,31 -25872,1518559455232,35 -25873,1518559492240,36 -25874,1518559568696,37 -25875,1518559784833,39 -25876,1518559904461,37 -25877,1518560233818,36 -25878,1518560403507,34 -25879,1518560530483,34 -25880,1518560626582,35 -25881,1518560704593,34 -25882,1518602689308,34 -25883,1518602737796,31 -25884,1518602881794,32 -25885,1518602949626,31 -25886,1518603059727,31 -25887,1518603113239,30 -25888,1518603171756,30 -25889,1518603188118,30 -25890,1518603314557,33 -25891,1518603389038,31 -25892,1518603537434,32 -25893,1518603593363,31 -25894,1518613928461,31 -25895,1518614093644,29 -25896,1518614369160,29 -25897,1518614471150,27 -25898,1518614771283,27 -25899,1518614954106,25 -25900,1518615030860,24 -25901,1518615443484,23 -25902,1518615512145,23 -25903,1518615542238,22 -25904,1518615683774,22 -25905,1518615880480,22 -25906,1518615955240,20 -25907,1518615998331,20 -25908,1518616121006,19 -25909,1518616150606,18 -25910,1518616247900,17 -25911,1518616291837,17 -25912,1518616374846,19 -25913,1518616415807,19 -25914,1518616476745,18 -25915,1518616601910,17 -25916,1518616662666,17 -25917,1518616738712,16 -25918,1518616794815,15 -25919,1518616956661,14 -25920,1518617050413,13 -25921,1518617125558,12 -25922,1518617191613,12 -25923,1518617209431,11 -25924,1518617259103,10 -25925,1518617312475,13 -25926,1518617332591,12 -25927,1518617405444,13 -25928,1518617441947,15 -25929,1518617486394,15 -25930,1518617508853,15 -25931,1518617580596,17 -25932,1518617691132,16 -25933,1518617735739,16 -25934,1518617762348,16 -25935,1518617776783,16 -25936,1518617844638,18 -25937,1518618009039,17 -25938,1518618036348,16 -25939,1518618058306,17 -25940,1518618098014,17 -25941,1518618110397,17 -25942,1518618178640,20 -25943,1518618196865,21 -25944,1518618257225,22 -25945,1518618362509,23 -25946,1518618513306,23 -25947,1518618558442,23 -25948,1518618613356,23 -25949,1518618749258,22 -25950,1518618790075,22 -25951,1518618857580,22 -25952,1518618900905,22 -25953,1518619043994,22 -25954,1518619092992,22 -25955,1518619112299,21 -25956,1518619124762,23 -25957,1518619159360,27 -25958,1518619275736,27 -25959,1518619304367,27 -25960,1518619346207,28 -25961,1518619379294,28 -25962,1518619468690,29 -25963,1518619583125,28 -25964,1518619668274,27 -25965,1518619869289,27 -25966,1518619953152,27 -25967,1518619979968,26 -25968,1518620323493,27 -25969,1518620412355,26 -25970,1518620502722,28 -25971,1518620648664,27 -25972,1518620695359,29 -25973,1518620827233,31 -25974,1518620957065,30 -25975,1518621022877,31 -25976,1518621176925,30 -25977,1518621246740,30 -25978,1518621387895,29 -25979,1518621529368,29 -25980,1518621714059,28 -25981,1518621893975,27 -25982,1518621993308,26 -25983,1518622024714,26 -25984,1518622118002,28 -25985,1518622290730,27 -25986,1518622343503,26 -25987,1518622508075,27 -25988,1518622684533,26 -25989,1518622747310,25 -25990,1518622827659,27 -25991,1518622916419,27 -25992,1518622962946,26 -25993,1518623118905,27 -25994,1518623154633,26 -25995,1518623239782,27 -25996,1518623276471,27 -25997,1518623437603,27 -25998,1518623535889,26 -25999,1518623698532,26 -26000,1518623737490,25 -26001,1518623783335,25 -26002,1518623951748,25 -26003,1518624046402,24 -26004,1518624197024,25 -26005,1518624220381,23 -26006,1518624242725,24 -26007,1518624273857,26 -26008,1518624314738,28 -26009,1518624330195,28 -26010,1518624372921,31 -26011,1518624448778,32 -26012,1518624682844,31 -26013,1518624871893,31 -26014,1518624932528,30 -26015,1518625059256,30 -26016,1518625151603,29 -26017,1518625326655,28 -26018,1518637335279,27 -26019,1518637363877,26 -26020,1518637401275,27 -26021,1518637546938,27 -26022,1518637662421,26 -26023,1518637763307,25 -26024,1518637863581,25 -26025,1518637991211,24 -26026,1518638064350,23 -26027,1518638193748,23 -26028,1518638212976,23 -26029,1518638257196,24 -26030,1518638356345,24 -26031,1518638390071,24 -26032,1518638596066,24 -26033,1518638636643,23 -26034,1518638791898,22 -26035,1518638817533,23 -26036,1518638907249,24 -26037,1518638973943,23 -26038,1518639048199,23 -26039,1518639125080,23 -26040,1518639227525,23 -26041,1518639387047,22 -26042,1518639438396,22 -26043,1518639456118,22 -26044,1518639558292,25 -26045,1518639597369,25 -26046,1518639646976,25 -26047,1518639828029,24 -26048,1518640039430,24 -26049,1518640125327,23 -26050,1518640153303,22 -26051,1518640268738,24 -26052,1518640295746,23 -26053,1518640331308,24 -26054,1518640455340,24 -26055,1518640538451,24 -26056,1518640674598,24 -26057,1518640704550,25 -26058,1518640756727,26 -26059,1518640818946,26 -26060,1518640877525,28 -26061,1518640937355,27 -26062,1518640954137,28 -26063,1518640995188,31 -26064,1518641078599,32 -26065,1518641111896,31 -26066,1518641303237,32 -26067,1518641355609,32 -26068,1518641474890,33 -26069,1518641614752,31 -26070,1518641693663,32 -26071,1518641822764,31 -26072,1518641963984,30 -26073,1518677579219,30 -26074,1518677718291,28 -26075,1518677795054,28 -26076,1518677918785,28 -26077,1518677996367,27 -26078,1518678042248,26 -26079,1518678062862,27 -26080,1518678157533,29 -26081,1518678255566,28 -26082,1518678475074,27 -26083,1518678609269,26 -26084,1518678686481,26 -26085,1518678794602,25 -26086,1518678984426,25 -26087,1518679142446,24 -26088,1518679257230,24 -26089,1518679355892,22 -26090,1518679422071,22 -26091,1518679463668,21 -26092,1518679472179,21 -26093,1518679562699,26 -26094,1518679745086,25 -26095,1518679806420,26 -26096,1518679853879,25 -26097,1518679865248,25 -26098,1518679877062,29 -26099,1518679917520,34 -26100,1518679983829,35 -26101,1518680075198,34 -26102,1518680220645,34 -26103,1518680262470,33 -26104,1518680335690,33 -26105,1518680367683,33 -26106,1518680475438,35 -26107,1518680625451,35 -26108,1518680664918,35 -26109,1518680851747,37 -26110,1518681115314,37 -26111,1518681182944,37 -26112,1518681402626,37 -26113,1518681423357,36 -26114,1518681474862,39 -26115,1518681546527,39 -26116,1518681672699,39 -26117,1518681899638,38 -26118,1518682011622,37 -26119,1518682169841,36 -26120,1518682209291,35 -26121,1518682445915,37 -26122,1518682601530,36 -26123,1518682702273,35 -26124,1518682886766,34 -26125,1518682901871,34 -26126,1518682918418,37 -26127,1518683054260,42 -26128,1518683091613,40 -26129,1518683210495,42 -26130,1518683345039,42 -26131,1518683469451,41 -26132,1518683502998,41 -26133,1518683656645,42 -26134,1518683773437,42 -26135,1518683889417,40 -26136,1518683975154,40 -26137,1518684004235,39 -26138,1518684114610,42 -26139,1518684182073,41 -26140,1518684545805,41 -26141,1518684598373,39 -26142,1518684847415,39 -26143,1518685106344,38 -26144,1518685206761,38 -26145,1518685334580,37 -26146,1518685357681,36 -26147,1518685458524,39 -26148,1518685497994,38 -26149,1518685568101,38 -26150,1518685626691,38 -26151,1518685758708,39 -26152,1518686043366,38 -26153,1518686135198,37 -26154,1518686178936,37 -26155,1518686265667,37 -26156,1518686602014,37 -26157,1518686664360,35 -26158,1518686808988,35 -26159,1518687062549,34 -26160,1518687158095,33 -26161,1518687329010,33 -26162,1518687560241,32 -26163,1518687693649,32 -26164,1518687821486,32 -26165,1518687926526,31 -26166,1518687990508,31 -26167,1518688230087,30 -26168,1518688238338,30 -26169,1518688389447,36 -26170,1518688415691,36 -26171,1518688518741,38 -26172,1518688631091,37 -26173,1518688818004,35 -26174,1518689071655,34 -26175,1518689274775,33 -26176,1518689353137,32 -26177,1518689529399,31 -26178,1518689710447,29 -26179,1518689865105,28 -26180,1518689956620,28 -26181,1518690028005,28 -26182,1518690124015,26 -26183,1518690320374,26 -26184,1518690407449,24 -26185,1518690455328,23 -26186,1518690521795,23 -26187,1518690633041,22 -26188,1518690689712,20 -26189,1518690818552,19 -26190,1518690876340,18 -26191,1518690898521,17 -26192,1518690917923,17 -26193,1518690963281,21 -26194,1518690986336,20 -26195,1518691094845,21 -26196,1518691113006,19 -26197,1518691212928,20 -26198,1518691294364,22 -26199,1518691397420,24 -26200,1518691451065,23 -26201,1518691565819,23 -26202,1518691711837,22 -26203,1518691758945,21 -26204,1518691807082,22 -26205,1518691886503,21 -26206,1518692032767,22 -26207,1518692084559,20 -26208,1518692155205,20 -26209,1518692194382,20 -26210,1518692222577,19 -26211,1518692259183,19 -26212,1518692282632,20 -26213,1518692321184,20 -26214,1518692398163,22 -26215,1518692447229,21 -26216,1518692472801,21 -26217,1518692645761,22 -26218,1518692676028,21 -26219,1518692755402,21 -26220,1518692828840,20 -26221,1518692853733,20 -26222,1518692993123,21 -26223,1518693057620,19 -26224,1518693073628,19 -26225,1518693135354,21 -26226,1518693329320,22 -26227,1518693389422,23 -26228,1518693450326,23 -26229,1518693469528,24 -26230,1518693516519,25 -26231,1518693551476,26 -26232,1518693618263,26 -26233,1518693705513,26 -26234,1518693816310,26 -26235,1518693938744,26 -26236,1518694132226,25 -26237,1518694200605,24 -26238,1518694400196,25 -26239,1518694422424,24 -26240,1518694512934,25 -26241,1518694657405,25 -26242,1518694711848,25 -26243,1518694803172,24 -26244,1518694894183,24 -26245,1518694929024,23 -26246,1518695065781,23 -26247,1518695163571,24 -26248,1518695239175,23 -26249,1518695278202,24 -26250,1518695331139,24 -26251,1518695361822,24 -26252,1518695545219,25 -26253,1518695648791,25 -26254,1518695660457,24 -26255,1518695743562,28 -26256,1518695833549,28 -26257,1518695979324,28 -26258,1518696113737,27 -26259,1518696270179,26 -26260,1518696333538,25 -26261,1518696427687,25 -26262,1518696443646,24 -26263,1518696521575,26 -26264,1518696589527,25 -26265,1518696700162,26 -26266,1518696757481,24 -26267,1518696845730,24 -26268,1518696898071,24 -26269,1518696995551,28 -26270,1518697155407,27 -26271,1518697215638,28 -26272,1518697467144,28 -26273,1518697564698,27 -26274,1518697624887,27 -26275,1518697774133,27 -26276,1518697806512,26 -26277,1518697924067,27 -26278,1518698119794,25 -26279,1518698340159,25 -26280,1518698421395,24 -26281,1518698460737,24 -26282,1518698535219,24 -26283,1518698565089,23 -26284,1518698791123,23 -26285,1518698848339,22 -26286,1518698859950,23 -26287,1518698891454,26 -26288,1518699015697,27 -26289,1518699025437,27 -26290,1518699150054,31 -26291,1518699226665,30 -26292,1518699268056,31 -26293,1518699380095,33 -26294,1518699430787,32 -26295,1518699501322,33 -26296,1518699705777,32 -26297,1518699830554,32 -26298,1518699902274,32 -26299,1518699938095,31 -26300,1518699995742,32 -26301,1518700076744,32 -26302,1518700220234,32 -26303,1518700288620,30 -26304,1518700319487,30 -26305,1518700385927,32 -26306,1518700470063,32 -26307,1518700530362,31 -26308,1518700612007,31 -26309,1518700688544,31 -26310,1518700896235,30 -26311,1518701005635,29 -26312,1518701260074,30 -26313,1518701844933,29 -26314,1518702031402,28 -26315,1518702103701,27 -26316,1518702147101,26 -26317,1518702171547,28 -26318,1518702301948,29 -26319,1518702388162,28 -26320,1518702443459,28 -26321,1518702596102,28 -26322,1518702639871,28 -26323,1518702761019,28 -26324,1518702796808,27 -26325,1518702850598,29 -26326,1518702918237,29 -26327,1518702976208,28 -26328,1518703075300,29 -26329,1518703116831,28 -26330,1518703154454,29 -26331,1518703194209,30 -26332,1518703264704,31 -26333,1518703281199,31 -26334,1518703307396,35 -26335,1518703416851,36 -26336,1518703448405,35 -26337,1518703501889,36 -26338,1518703564463,36 -26339,1518703710322,36 -26340,1518703764443,36 -26341,1518703818362,36 -26342,1518703852281,36 -26343,1518704008776,38 -26344,1518704156119,37 -26345,1518704317950,36 -26346,1518704422344,35 -26347,1518704531131,34 -26348,1518704714839,33 -26349,1518704802988,33 -26350,1518704883275,33 -26351,1518705014726,32 -26352,1518705289518,32 -26353,1518705407424,31 -26354,1518705474642,29 -26355,1518705652388,32 -26356,1518705811282,30 -26357,1518705882527,29 -26358,1518706166467,29 -26359,1518710570740,28 -26360,1518710600940,26 -26361,1518710612681,27 -26362,1518710616545,31 -26363,1518710639278,51 -26364,1518710677607,54 -26365,1518710703269,55 -26366,1518710848622,60 -26367,1518711010027,59 -26368,1518711152063,57 -26369,1518711198838,57 -26370,1518711322328,58 -26371,1518711492999,57 -26372,1518711553527,56 -26373,1518711589799,56 -26374,1518711814655,57 -26375,1518711851193,56 -26376,1518711874005,58 -26377,1518712010452,63 -26378,1518712119603,62 -26379,1518712178593,61 -26380,1518712517512,61 -26381,1518712526711,60 -26382,1518712843852,73 -26383,1518712917560,72 -26384,1518712940601,72 -26385,1518715786530,77 -26386,1518716079192,75 -26387,1518716355603,74 -26388,1518717498776,74 -26389,1518717743409,71 -26390,1518717826043,73 -26391,1518717913505,72 -26392,1518718039473,72 -26393,1518718368679,72 -26394,1518718383040,70 -26395,1518718602419,80 -26396,1518718945833,78 -26397,1518719475654,76 -26398,1518719682572,74 -26399,1518719952228,73 -26400,1518720147561,72 -26401,1518720271994,70 -26402,1518720424608,70 -26403,1518720694276,68 -26404,1518720773918,66 -26405,1518720890089,67 -26406,1518721126233,66 -26407,1518721285627,64 -26408,1518721484477,63 -26409,1518721595187,62 -26410,1518721696911,61 -26411,1518721890828,59 -26412,1518721974104,57 -26413,1518722145627,57 -26414,1518722357793,54 -26415,1518722622431,52 -26416,1518722665889,50 -26417,1518722760389,51 -26418,1518722800616,51 -26419,1518722855675,51 -26420,1518722982504,51 -26421,1518723026479,50 -26422,1518723180027,50 -26423,1518723384183,49 -26424,1518723703640,46 -26425,1518723772079,44 -26426,1518724117027,44 -26427,1518724221507,42 -26428,1518724358008,40 -26429,1518724416831,39 -26430,1518724473869,38 -26431,1518724640510,38 -26432,1518724795683,37 -26433,1518724822153,35 -26434,1518724839481,37 -26435,1518725038139,41 -26436,1518725134093,39 -26437,1518725178396,39 -26438,1518725213331,38 -26439,1518725547117,39 -26440,1518725668258,37 -26441,1518725740497,35 -26442,1518725928497,35 -26443,1518726082437,34 -26444,1518726214973,32 -26445,1518726339418,30 -26446,1518726419725,28 -26447,1518726464975,27 -26448,1518726591096,25 -26449,1518726671436,23 -26450,1518726835412,21 -26451,1518726944733,19 -26452,1518726970312,18 -26453,1518727093162,16 -26454,1518727222380,14 -26455,1518727276847,12 -26456,1518727317936,11 -26457,1518727325788,8 -26458,1518727367533,8 -26459,1518727395962,6 -26460,1518727440596,4 -26461,1518727463989,2 -26462,1518727471805,2 -26463,1518727485103,10 -26464,1518727493913,12 -26465,1518727526650,15 -26466,1518727558150,16 -26467,1518727652521,15 -26468,1518727730094,14 -26469,1518727765872,13 -26470,1518727810520,13 -26471,1518727871361,12 -26472,1518727897216,10 -26473,1518727924318,10 -26474,1518727947402,11 -26475,1518728045388,10 -26476,1518728144819,10 -26477,1518728159659,11 -26478,1518728198228,11 -26479,1518728253951,10 -26480,1518728307404,10 -26481,1518728349395,8 -26482,1518728381225,15 -26483,1518728395567,15 -26484,1518728407151,17 -26485,1518728465001,22 -26486,1518728530225,21 -26487,1518728649965,21 -26488,1518728782912,19 -26489,1518728894034,18 -26490,1518728961185,17 -26491,1518728993268,17 -26492,1518729029039,18 -26493,1518729115782,18 -26494,1518729167617,16 -26495,1518729222071,22 -26496,1518729263271,21 -26497,1518729335697,21 -26498,1518729401357,20 -26499,1518729507392,20 -26500,1518729519140,20 -26501,1518729580611,22 -26502,1518729627913,22 -26503,1518729717650,22 -26504,1518729796823,22 -26505,1518729914356,21 -26506,1518730012906,21 -26507,1518730021654,20 -26508,1518730139486,24 -26509,1518730181523,23 -26510,1518730219937,24 -26511,1518730271149,25 -26512,1518730368658,24 -26513,1518730441343,24 -26514,1518730657819,23 -26515,1518730728560,23 -26516,1518730759122,22 -26517,1518730827659,24 -26518,1518730858901,24 -26519,1518731012509,26 -26520,1518731030282,25 -26521,1518731193453,28 -26522,1518731286811,27 -26523,1518731307272,27 -26524,1518731347065,29 -26525,1518731413620,29 -26526,1518731524123,29 -26527,1518731630621,28 -26528,1518731766027,28 -26529,1518731820397,27 -26530,1518731893165,28 -26531,1518732027591,28 -26532,1518732038818,27 -26533,1518732109137,31 -26534,1518732211497,33 -26535,1518732293900,34 -26536,1518732402470,34 -26537,1518732502199,33 -26538,1518732527948,34 -26539,1518732595758,36 -26540,1518732804416,36 -26541,1518732882507,35 -26542,1518732982126,36 -26543,1518733076603,35 -26544,1518733103121,34 -26545,1518733168791,36 -26546,1518733271838,36 -26547,1518733348720,36 -26548,1518733436092,36 -26549,1518733724525,36 -26550,1518733851710,35 -26551,1518734019641,34 -26552,1518734163175,33 -26553,1518734232290,32 -26554,1518734265850,32 -26555,1518734316556,33 -26556,1518734391832,33 -26557,1518734453910,33 -26558,1518734541311,33 -26559,1518734634863,33 -26560,1518734722131,33 -26561,1518734791318,32 -26562,1518734839155,31 -26563,1518734981069,31 -26564,1518735146148,31 -26565,1518735237203,32 -26566,1518735384878,31 -26567,1518735442990,31 -26568,1518735721245,30 -26569,1518735816686,29 -26570,1518735993578,29 -26571,1518736143359,28 -26572,1518736330498,27 -26573,1518736433233,26 -26574,1518736472660,26 -26575,1518736487441,26 -26576,1518736576610,28 -26577,1518736659766,28 -26578,1518736689288,27 -26579,1518736755649,28 -26580,1518736889790,28 -26581,1518737098702,26 -26582,1518737119687,25 -26583,1518737164790,27 -26584,1518737255209,28 -26585,1518737315354,29 -26586,1518737360370,29 -26587,1518737688400,29 -26588,1518737743331,27 -26589,1518737845821,28 -26590,1518737960221,27 -26591,1518738016831,26 -26592,1518738089362,25 -26593,1518738223706,25 -26594,1518738250048,24 -26595,1518738390454,25 -26596,1518738565160,24 -26597,1518738590687,23 -26598,1518738685954,24 -26599,1518738995670,24 -26600,1518739044666,22 -26601,1518739091431,24 -26602,1518739142561,24 -26603,1518739170379,23 -26604,1518739357480,24 -26605,1518739405995,23 -26606,1518739451977,23 -26607,1518739478661,22 -26608,1518739520622,25 -26609,1518739551097,26 -26610,1518739568409,26 -26611,1518739623437,29 -26612,1518739679839,29 -26613,1518739786257,29 -26614,1518739841504,28 -26615,1518739926417,27 -26616,1518740017034,27 -26617,1518740052229,26 -26618,1518740176455,27 -26619,1518740215467,27 -26620,1518740290937,27 -26621,1518740442916,28 -26622,1518740582126,27 -26623,1518740651909,26 -26624,1518740751499,27 -26625,1518740835725,27 -26626,1518740961681,26 -26627,1518740976758,25 -26628,1518740988525,28 -26629,1518741134538,32 -26630,1518741148371,32 -26631,1518741327566,36 -26632,1518741415152,35 -26633,1518741502221,36 -26634,1518741541251,37 -26635,1518741650021,37 -26636,1518741764200,36 -26637,1518741917315,36 -26638,1518742083096,35 -26639,1518742155261,36 -26640,1518742358783,35 -26641,1518742425043,34 -26642,1518742589856,34 -26643,1518742645733,33 -26644,1518742716313,33 -26645,1518742814931,34 -26646,1518742931309,34 -26647,1518742975920,34 -26648,1518743107169,34 -26649,1518743209425,33 -26650,1518743258361,33 -26651,1518743513924,33 -26652,1518743588373,31 -26653,1518743714944,31 -26654,1518744019335,31 -26655,1518744055961,30 -26656,1518744208911,31 -26657,1518744226629,31 -26658,1518744467146,34 -26659,1518744598786,33 -26660,1518744622658,32 -26661,1518744676238,34 -26662,1518744760331,34 -26663,1518744783335,34 -26664,1518744892048,36 -26665,1518744973636,35 -26666,1518745112179,35 -26667,1518745244656,34 -26668,1518745403660,34 -26669,1518745520136,33 -26670,1518745605039,31 -26671,1518745683812,31 -26672,1518745758174,30 -26673,1518745804866,30 -26674,1518745953876,30 -26675,1518746128411,28 -26676,1518746186143,28 -26677,1518746326193,29 -26678,1518746395366,29 -26679,1518746471317,28 -26680,1518746577037,28 -26681,1518746650925,27 -26682,1518746753093,27 -26683,1518746804452,27 -26684,1518746834675,27 -26685,1518747043899,27 -26686,1518747107795,27 -26687,1518747174263,27 -26688,1518747191749,27 -26689,1518747262980,29 -26690,1518747389842,29 -26691,1518747483422,27 -26692,1518747491686,26 -26693,1518747583858,33 -26694,1518747598258,32 -26695,1518747715009,37 -26696,1518747768116,36 -26697,1518747793754,36 -26698,1518747938028,38 -26699,1518748132047,37 -26700,1518748215600,35 -26701,1518748254550,35 -26702,1518748299935,36 -26703,1518748453082,36 -26704,1518748555274,36 -26705,1518748614865,35 -26706,1518749035175,35 -26707,1518749085289,33 -26708,1518749379522,34 -26709,1518749447110,33 -26710,1518749520598,34 -26711,1518749664864,34 -26712,1518749768871,33 -26713,1518750226641,33 -26714,1518750373599,31 -26715,1518750432818,31 -26716,1518750516226,31 -26717,1518750656029,30 -26718,1518750717691,30 -26719,1518750845837,29 -26720,1518751003491,28 -26721,1518751262252,27 -26722,1518751384117,26 -26723,1518751433281,25 -26724,1518751462184,25 -26725,1518751483178,25 -26726,1518751494630,26 -26727,1518751690066,31 -26728,1518751738197,31 -26729,1518751822137,33 -26730,1518751866219,32 -26731,1518752025507,36 -26732,1518752141195,35 -26733,1518752220575,34 -26734,1518752271571,33 -26735,1518752465405,34 -26736,1518752635996,33 -26737,1518752839708,33 -26738,1518752886531,31 -26739,1518752911736,31 -26740,1518753013733,33 -26741,1518753102161,32 -26742,1518753196887,32 -26743,1518753296709,31 -26744,1518753428325,30 -26745,1518753592865,29 -26746,1518753673724,29 -26747,1518753723576,28 -26748,1518753851157,29 -26749,1518753986425,28 -26750,1518754055751,27 -26751,1518754246128,27 -26752,1518754416408,26 -26753,1518754559735,25 -26754,1518754659649,23 -26755,1518754694995,22 -26756,1518754896797,22 -26757,1518754922727,22 -26758,1518755007325,24 -26759,1518755150575,23 -26760,1518755200267,22 -26761,1518755289848,22 -26762,1518755348003,22 -26763,1518755682115,22 -26764,1518755712519,22 -26765,1518755780838,22 -26766,1518755835843,23 -26767,1518755864435,22 -26768,1518755919473,22 -26769,1518756100627,22 -26770,1518756147195,21 -26771,1518756200358,21 -26772,1518756226595,20 -26773,1518756294596,21 -26774,1518756346427,21 -26775,1518756459333,20 -26776,1518756488093,19 -26777,1518756544699,20 -26778,1518756683846,19 -26779,1518756725121,18 -26780,1518756882130,18 -26781,1518756935352,17 -26782,1518756998269,17 -26783,1518757101852,16 -26784,1518757154390,15 -26785,1518757245575,15 -26786,1518757301759,14 -26787,1518757397028,13 -26788,1518757424566,12 -26789,1518757441940,14 -26790,1518757468078,14 -26791,1518757569731,15 -26792,1518757610957,14 -26793,1518757619134,16 -26794,1518757676202,20 -26795,1518757702885,22 -26796,1518757717698,23 -26797,1518757795321,26 -26798,1518757859095,27 -26799,1518757921785,26 -26800,1518757936550,27 -26801,1518757989808,30 -26802,1518758029113,30 -26803,1518758190377,32 -26804,1518758272452,31 -26805,1518758293935,31 -26806,1518758339725,34 -26807,1518758533015,34 -26808,1518758582087,33 -26809,1518758630384,33 -26810,1518758729521,34 -26811,1518758787700,34 -26812,1518758853056,33 -26813,1518758893413,34 -26814,1518758982166,34 -26815,1518759107753,33 -26816,1518759228678,33 -26817,1518759427229,33 -26818,1518759739382,31 -26819,1518759823393,30 -26820,1518759869352,30 -26821,1518759926717,30 -26822,1518760101994,30 -26823,1518760232517,29 -26824,1518760295510,28 -26825,1518760426063,28 -26826,1518760464561,29 -26827,1518760546482,32 -26828,1518760573203,31 -26829,1518760580997,34 -26830,1518760646682,43 -26831,1518760776390,43 -26832,1518760870213,42 -26833,1518761233817,43 -26834,1518761408675,41 -26835,1518761484809,41 -26836,1518761566818,41 -26837,1518761670161,40 -26838,1518761767828,40 -26839,1518761826173,40 -26840,1518761861221,41 -26841,1518762116824,42 -26842,1518762329635,41 -26843,1518762402112,41 -26844,1518762450560,41 -26845,1518762716184,41 -26846,1518762740565,40 -26847,1518762785773,42 -26848,1518762905556,44 -26849,1518763054942,42 -26850,1518763088253,41 -26851,1518763315041,43 -26852,1518763492490,42 -26853,1518763512932,41 -26854,1518763646685,44 -26855,1518763822279,43 -26856,1518764010124,43 -26857,1518764160312,41 -26858,1518764225015,41 -26859,1518764288256,41 -26860,1518764494641,40 -26861,1518764632478,40 -26862,1518764668441,38 -26863,1518764688834,40 -26864,1518764803764,42 -26865,1518764914702,43 -26866,1518765078569,41 -26867,1518765268591,41 -26868,1518765294943,40 -26869,1518765407410,42 -26870,1518765442160,41 -26871,1518765481681,42 -26872,1518765524223,43 -26873,1518765609978,44 -26874,1518765627150,44 -26875,1518765810721,48 -26876,1518765944321,47 -26877,1518766400611,47 -26878,1518766478146,45 -26879,1518766550500,45 -26880,1518766629036,44 -26881,1518766818767,43 -26882,1518766946079,42 -26883,1518767080275,41 -26884,1518767481985,39 -26885,1518767623484,38 -26886,1518767739720,36 -26887,1518768198909,35 -26888,1518768210404,33 -26889,1518768306129,39 -26890,1518768404684,39 -26891,1518768522219,37 -26892,1518768588737,36 -26893,1518768733578,36 -26894,1518768851943,36 -26895,1518769103341,35 -26896,1518769178700,34 -26897,1518769223214,35 -26898,1518769269099,35 -26899,1518769371923,35 -26900,1518769600220,34 -26901,1518769690294,34 -26902,1518769837541,34 -26903,1518769921315,33 -26904,1518769936297,33 -26905,1518769978777,36 -26906,1518770055357,37 -26907,1518770130484,38 -26908,1518770183543,37 -26909,1518770510373,37 -26910,1518770703911,36 -26911,1518770810382,35 -26912,1518770886602,34 -26913,1518770930108,34 -26914,1518770965372,34 -26915,1518771168517,34 -26916,1518771355309,34 -26917,1518771572015,32 -26918,1518771630928,30 -26919,1518771843107,29 -26920,1518771925069,28 -26921,1518772128510,28 -26922,1518772153971,26 -26923,1518772175860,27 -26924,1518772218187,28 -26925,1518772337445,28 -26926,1518772359179,27 -26927,1518772420817,28 -26928,1518772673732,27 -26929,1518772836239,27 -26930,1518772954060,31 -26931,1518773008549,30 -26932,1518773203896,30 -26933,1518773324174,28 -26934,1518773379728,27 -26935,1518773508718,27 -26936,1518773626659,26 -26937,1518773824895,25 -26938,1518773903630,24 -26939,1518774014085,23 -26940,1518774067851,22 -26941,1518774080781,23 -26942,1518774255078,25 -26943,1518774412226,24 -26944,1518774618868,23 -26945,1518774669135,22 -26946,1518774859838,22 -26947,1518775001638,21 -26948,1518775045342,21 -26949,1518775110129,21 -26950,1518775185025,19 -26951,1518775220660,20 -26952,1518775271305,20 -26953,1518775301553,19 -26954,1518775384756,22 -26955,1518775450083,21 -26956,1518775549469,19 -26957,1518775649639,19 -26958,1518775692812,17 -26959,1518775817059,17 -26960,1518775911998,16 -26961,1518776020239,15 -26962,1518776075059,14 -26963,1518776111395,14 -26964,1518776123761,16 -26965,1518776190861,18 -26966,1518776224050,17 -26967,1518776281552,17 -26968,1518776321048,16 -26969,1518776358102,17 -26970,1518776448092,17 -26971,1518776567823,17 -26972,1518776587447,17 -26973,1518776635016,19 -26974,1518776746014,19 -26975,1518776780135,21 -26976,1518776831704,21 -26977,1518776954934,20 -26978,1518777076032,19 -26979,1518777108387,19 -26980,1518777264381,19 -26981,1518777302612,20 -26982,1518777345968,19 -26983,1518777373865,19 -26984,1518777483759,20 -26985,1518777675717,18 -26986,1518777887229,18 -26987,1518777921270,17 -26988,1518777972566,16 -26989,1518778041107,19 -26990,1518778124508,18 -26991,1518778201200,18 -26992,1518778210362,17 -26993,1518778336433,21 -26994,1518778449751,20 -26995,1518778629893,19 -26996,1518778724961,19 -26997,1518778785302,18 -26998,1518778873537,18 -26999,1518778917025,18 -27000,1518779064445,18 -27001,1518779204566,17 -27002,1518779310666,16 -27003,1518779384983,15 -27004,1518779440228,15 -27005,1518779497753,17 -27006,1518779660000,17 -27007,1518779703073,17 -27008,1518779809090,16 -27009,1518779894316,17 -27010,1518779932413,16 -27011,1518780006657,16 -27012,1518780146197,16 -27013,1518780210230,15 -27014,1518780288432,15 -27015,1518780311811,15 -27016,1518780333862,16 -27017,1518780387188,17 -27018,1518780478939,17 -27019,1518780494415,16 -27020,1518780525451,17 -27021,1518780537961,18 -27022,1518780648053,20 -27023,1518780668048,21 -27024,1518780765128,23 -27025,1518780861151,23 -27026,1518780908382,23 -27027,1518780961481,24 -27028,1518781062928,24 -27029,1518781214006,24 -27030,1518781234763,24 -27031,1518781335416,25 -27032,1518781345191,25 -27033,1518781416073,29 -27034,1518781511833,30 -27035,1518781657117,30 -27036,1518781737035,29 -27037,1518781945664,29 -27038,1518782066815,28 -27039,1518782147881,27 -27040,1518782314755,27 -27041,1518782385747,26 -27042,1518782483501,28 -27043,1518782562766,28 -27044,1518782831655,27 -27045,1518782996896,26 -27046,1518783042061,26 -27047,1518783204617,25 -27048,1518783367569,25 -27049,1518783393264,25 -27050,1518788356084,26 -27051,1518788395941,25 -27052,1518788462440,26 -27053,1518788504552,26 -27054,1518788532442,26 -27055,1518788574680,28 -27056,1518788618084,28 -27057,1518788666797,28 -27058,1518788924608,29 -27059,1518789047375,28 -27060,1518789147660,27 -27061,1518789163992,27 -27062,1518789235704,29 -27063,1518789443500,30 -27064,1518789458027,28 -27065,1518789545463,33 -27066,1518789691882,32 -27067,1518789855484,33 -27068,1518789894294,32 -27069,1518789940110,33 -27070,1518790080606,33 -27071,1518790199963,33 -27072,1518790366294,32 -27073,1518790462380,32 -27074,1518790591335,32 -27075,1518790661693,31 -27076,1518790740167,31 -27077,1518790790283,32 -27078,1518790807636,31 -27079,1518790837186,35 -27080,1518790978934,37 -27081,1518791073039,36 -27082,1518791378111,36 -27083,1518791576205,35 -27084,1518791744539,34 -27085,1518791786277,33 -27086,1518791863811,33 -27087,1518792011533,33 -27088,1518792230764,33 -27089,1518792278094,32 -27090,1518792357360,32 -27091,1518792586668,32 -27092,1518792815422,31 -27093,1518792924648,32 -27094,1518793016301,31 -27095,1518793045884,31 -27096,1518793067748,32 -27097,1518793205480,33 -27098,1518793363118,33 -27099,1518793489703,33 -27100,1518793797356,32 -27101,1518793917976,30 -27102,1518794013965,29 -27103,1518794071714,29 -27104,1518794175853,29 -27105,1518794307320,28 -27106,1518794328517,27 -27107,1518794420856,28 -27108,1518794585849,28 -27109,1518794734492,27 -27110,1518794837719,26 -27111,1518794886391,26 -27112,1518794934090,25 -27113,1518795013338,25 -27114,1518795172308,24 -27115,1518795505618,23 -27116,1518795748023,22 -27117,1518795799987,22 -27118,1518795855364,22 -27119,1518795889398,21 -27120,1518796085323,22 -27121,1518796127952,21 -27122,1518796224736,22 -27123,1518796277533,22 -27124,1518796373305,23 -27125,1518796394971,22 -27126,1518796504528,23 -27127,1518796612338,23 -27128,1518796752658,22 -27129,1518796807985,21 -27130,1518796892503,20 -27131,1518797166141,21 -27132,1518797172439,19 -27133,1518797178720,29 -27134,1518797220450,38 -27135,1518797236929,39 -27136,1518797255647,43 -27137,1518797302863,47 -27138,1518797375209,48 -27139,1518797383996,47 -27140,1518797395045,58 -27141,1518797401238,69 -27142,1518797405020,95 -27143,1518797498848,153 -27144,1518797763427,153 -27145,1518798072029,150 -27146,1518798236385,148 -27147,1518798646440,148 -27148,1518798722092,145 -27149,1518798736231,146 -27150,1518801242906,168 -27151,1518801352858,164 -27152,1518801391312,165 -27153,1518801737597,171 -27154,1518802434943,168 -27155,1518802505020,166 -27156,1518802648463,168 -27157,1518802886347,168 -27158,1518802983145,165 -27159,1518803147091,165 -27160,1518803547985,164 -27161,1518803709266,161 -27162,1518804079551,161 -27163,1518804285042,158 -27164,1518804590108,155 -27165,1518804703790,154 -27166,1518805266383,154 -27167,1518805450327,150 -27168,1518806924671,148 -27169,1518807044941,145 -27170,1518807206049,144 -27171,1518807403084,142 -27172,1518807571682,140 -27173,1518808041297,138 -27174,1518808268527,134 -27175,1518808516972,132 -27176,1518808702071,129 -27177,1518808844212,126 -27178,1518809359574,125 -27179,1518809651440,123 -27180,1518809925713,121 -27181,1518809996735,117 -27182,1518810380678,117 -27183,1518810780644,114 -27184,1518810911161,111 -27185,1518811002182,108 -27186,1518811031861,108 -27187,1518811123153,112 -27188,1518811331463,111 -27189,1518811390345,107 -27190,1518811440369,107 -27191,1518811474401,109 -27192,1518811605787,111 -27193,1518811764258,109 -27194,1518811922433,106 -27195,1518812135592,103 -27196,1518812178613,100 -27197,1518812238313,103 -27198,1518812387411,102 -27199,1518812757121,99 -27200,1518813111197,95 -27201,1518813199692,90 -27202,1518813429245,89 -27203,1518813578214,83 -27204,1518813998600,81 -27205,1518814286040,76 -27206,1518814299452,72 -27207,1518814372828,81 -27208,1518814791679,79 -27209,1518815205359,75 -27210,1518815796175,71 -27211,1518815848210,66 -27212,1518815964631,64 -27213,1518816133933,61 -27214,1518816385414,56 -27215,1518816561654,52 -27216,1518816608670,47 -27217,1518817124814,44 -27218,1518817405787,40 -27219,1518817745122,35 -27220,1518817919146,31 -27221,1518818022066,27 -27222,1518818190750,22 -27223,1518818257354,17 -27224,1518818307954,13 -27225,1518818348349,8 -27226,1518818388614,6 -27227,1518818424498,1 -27228,1518818438159,1 -27229,1518818447905,1 -27230,1518818458549,1 -27231,1518818468334,1 -27232,1518818477519,1 -27233,1518818487677,1 -27234,1518818497477,1 -27235,1518818507381,1 -27236,1518818524059,1 -27237,1518818533635,1 -27238,1518818544011,1 -27239,1518818552882,1 -27240,1518818562680,1 -27241,1518818571748,1 -27242,1518818582012,1 -27243,1518818592929,2 -27244,1518818604326,2 -27245,1518818614944,1 -27246,1518818626091,1 -27247,1518818639612,1 -27248,1518818653362,1 -27249,1518818667801,1 -27250,1518818678230,4 -27251,1518818706109,3 -27252,1518818716279,2 -27253,1518818729781,5 -27254,1518818739456,5 -27255,1518818779763,4 -27256,1518818813692,4 -27257,1518818872477,4 -27258,1518818901633,2 -27259,1518818925306,3 -27260,1518818935477,2 -27261,1518818944520,1 -27262,1518818957993,1 -27263,1518818971078,1 -27264,1518818988453,1 -27265,1518818997622,1 -27266,1518819007783,1 -27267,1518819017832,1 -27268,1518819028145,1 -27269,1518819038071,1 -27270,1518819047795,1 -27271,1518819057259,1 -27272,1518819071050,1 -27273,1518819080980,1 -27274,1518819090305,1 -27275,1518819103959,1 -27276,1518819117802,1 -27277,1518819127464,1 -27278,1518819137601,1 -27279,1518819151297,1 -27280,1518819164937,1 -27281,1518819174584,1 -27282,1518819183774,1 -27283,1518819193314,1 -27284,1518819202433,1 -27285,1518819211881,1 -27286,1518819222824,1 -27287,1518819236209,1 -27288,1518819245555,1 -27289,1518819259576,1 -27290,1518819277211,1 -27291,1518819291654,1 -27292,1518819301692,1 -27293,1518819310868,1 -27294,1518819320808,1 -27295,1518819330387,1 -27296,1518819339644,1 -27297,1518819350436,1 -27298,1518819359607,1 -27299,1518819373690,1 -27300,1518819383036,1 -27301,1518819392290,1 -27302,1518819406096,1 -27303,1518819415366,1 -27304,1518819425359,1 -27305,1518819435053,1 -27306,1518819456378,1 -27307,1518819465294,1 -27308,1518819475193,2 -27309,1518819485785,2 -27310,1518819498895,2 -27311,1518819508718,2 -27312,1518819521841,4 -27313,1518819535139,5 -27314,1518819578600,6 -27315,1518819592030,6 -27316,1518819608856,6 -27317,1518819626476,8 -27318,1518819643802,9 -27319,1518819661022,10 -27320,1518819681978,10 -27321,1518819717419,12 -27322,1518819732219,12 -27323,1518819755477,13 -27324,1518819799211,15 -27325,1518819911615,16 -27326,1518819975586,16 -27327,1518820007420,15 -27328,1518820086056,17 -27329,1518820130160,16 -27330,1518820256461,16 -27331,1518820293388,17 -27332,1518820303705,17 -27333,1518820396572,20 -27334,1518820507964,20 -27335,1518820610437,20 -27336,1518820708162,20 -27337,1518820815891,20 -27338,1518820875569,20 -27339,1518820945544,20 -27340,1518821045954,21 -27341,1518821291680,21 -27342,1518821313272,20 -27343,1518821465670,21 -27344,1518821504991,21 -27345,1518821547280,22 -27346,1518821678152,23 -27347,1518821828368,23 -27348,1518821841187,22 -27349,1518821952278,26 -27350,1518822175666,25 -27351,1518822373040,26 -27352,1518822575422,25 -27353,1518822674203,24 -27354,1518823027902,25 -27355,1518823068491,25 -27356,1518823152862,26 -27357,1518823371805,25 -27358,1518823592040,25 -27359,1518823608300,25 -27360,1518823667673,28 -27361,1518823780679,28 -27362,1518823908011,28 -27363,1518823988183,28 -27364,1518824111330,28 -27365,1518824194620,27 -27366,1518824320319,28 -27367,1518824363927,27 -27368,1518824714577,28 -27369,1518824867411,27 -27370,1518825006929,27 -27371,1518825231832,27 -27372,1518825438853,26 -27373,1518825472568,25 -27374,1518825670204,26 -27375,1518825739427,26 -27376,1518825898152,26 -27377,1518825931001,25 -27378,1518826033888,27 -27379,1518826060621,26 -27380,1518826136581,27 -27381,1518826169699,27 -27382,1518826263853,29 -27383,1518826345203,29 -27384,1518826523875,28 -27385,1518826593847,27 -27386,1518826702361,27 -27387,1518826753990,27 -27388,1518826779140,27 -27389,1518826864838,29 -27390,1518826979001,28 -27391,1518827150267,28 -27392,1518827404859,27 -27393,1518827521309,27 -27394,1518827576795,26 -27395,1518828118677,26 -27396,1518828214624,24 -27397,1518828290417,25 -27398,1518828398973,24 -27399,1518828511804,23 -27400,1518828752970,22 -27401,1518828868515,21 -27402,1518829047920,21 -27403,1518829091426,21 -27404,1518829143076,20 -27405,1518829186794,20 -27406,1518829364953,20 -27407,1518829405893,19 -27408,1518829587182,19 -27409,1518829668237,18 -27410,1518829768410,18 -27411,1518829903561,18 -27412,1518829979598,17 -27413,1518830179569,16 -27414,1518830205285,15 -27415,1518830351469,16 -27416,1518830457599,16 -27417,1518830506755,15 -27418,1518830552563,15 -27419,1518830584008,15 -27420,1518830626657,15 -27421,1518830693044,15 -27422,1518830788565,15 -27423,1518831048778,16 -27424,1518831115337,15 -27425,1518831150991,15 -27426,1518831165471,15 -27427,1518831246393,16 -27428,1518831282355,16 -27429,1518831304148,17 -27430,1518831362954,17 -27431,1518831462073,17 -27432,1518831519762,16 -27433,1518831591079,18 -27434,1518831619528,18 -27435,1518831668781,18 -27436,1518831731320,18 -27437,1518831860083,18 -27438,1518831952706,17 -27439,1518832008840,17 -27440,1518832213088,17 -27441,1518832260088,16 -27442,1518832288576,15 -27443,1518832343695,17 -27444,1518832392585,16 -27445,1518832474212,17 -27446,1518832545660,17 -27447,1518832619265,16 -27448,1518832655101,16 -27449,1518832719148,18 -27450,1518832812454,17 -27451,1518832931503,17 -27452,1518832982518,17 -27453,1518833015236,16 -27454,1518833220727,16 -27455,1518833300200,15 -27456,1518833469359,16 -27457,1518833517828,15 -27458,1518833582607,15 -27459,1518833636647,14 -27460,1518833658650,15 -27461,1518833721636,17 -27462,1518833799013,16 -27463,1518833854149,17 -27464,1518833916628,17 -27465,1518833992362,16 -27466,1518834006532,16 -27467,1518834087302,18 -27468,1518834114687,18 -27469,1518834173705,18 -27470,1518834244435,18 -27471,1518834343423,18 -27472,1518834411144,17 -27473,1518834435950,17 -27474,1518834494451,18 -27475,1518834541666,18 -27476,1518834605631,18 -27477,1518834627172,18 -27478,1518834666675,20 -27479,1518834725066,20 -27480,1518834746193,21 -27481,1518834806695,23 -27482,1518834880032,23 -27483,1518834911122,24 -27484,1518835055707,24 -27485,1518835132608,23 -27486,1518835178818,24 -27487,1518835376097,24 -27488,1518835491819,24 -27489,1518835543186,24 -27490,1518835633880,24 -27491,1518835677388,24 -27492,1518835760216,25 -27493,1518835772894,24 -27494,1518835962877,28 -27495,1518836090029,27 -27496,1518836161010,27 -27497,1518836221759,27 -27498,1518836293705,28 -27499,1518836422404,27 -27500,1518836495577,27 -27501,1518836533810,27 -27502,1518836589274,27 -27503,1518836806940,27 -27504,1518836850255,27 -27505,1518836916776,28 -27506,1518837031612,28 -27507,1518837128153,27 -27508,1518837240210,27 -27509,1518837304710,27 -27510,1518837371106,26 -27511,1518837519777,27 -27512,1518837558620,26 -27513,1518837725084,26 -27514,1518837769220,26 -27515,1518837819274,26 -27516,1518838066159,27 -27517,1518838090652,25 -27518,1518838150020,27 -27519,1518838243829,28 -27520,1518838359888,27 -27521,1518838426387,27 -27522,1518838491599,26 -27523,1518838563626,26 -27524,1518838612156,26 -27525,1518838698476,26 -27526,1518838748670,25 -27527,1518838830614,26 -27528,1518838870297,27 -27529,1518838911138,28 -27530,1518838969507,29 -27531,1518839017257,28 -27532,1518839127936,29 -27533,1518839238940,28 -27534,1518839488667,28 -27535,1518839684132,28 -27536,1518839773519,27 -27537,1518839829122,26 -27538,1518839914023,27 -27539,1518839959048,26 -27540,1518840105071,26 -27541,1518840203649,26 -27542,1518840264249,25 -27543,1518840380455,25 -27544,1518840518487,25 -27545,1518840611065,25 -27546,1518840679751,24 -27547,1518840784400,23 -27548,1518840825019,23 -27549,1518841018827,23 -27550,1518841055257,22 -27551,1518841170509,23 -27552,1518841206842,23 -27553,1518841299656,23 -27554,1518841377310,23 -27555,1518841424133,21 -27556,1518841484123,22 -27557,1518841497263,22 -27558,1518841507396,24 -27559,1518841797460,29 -27560,1518841851344,28 -27561,1518841901768,29 -27562,1518842152969,28 -27563,1518842201581,27 -27564,1518842256655,28 -27565,1518842286308,27 -27566,1518842476324,28 -27567,1518842603401,29 -27568,1518842736070,28 -27569,1518842832042,28 -27570,1518842898917,27 -27571,1518842919567,27 -27572,1518843097380,29 -27573,1518843227584,27 -27574,1518843257315,27 -27575,1518843333378,28 -27576,1518843392715,28 -27577,1518843451596,27 -27578,1518843566228,28 -27579,1518843723549,28 -27580,1518843867715,28 -27581,1518843915297,27 -27582,1518843954996,28 -27583,1518844127521,28 -27584,1518844231664,28 -27585,1518844389455,27 -27586,1518844554508,26 -27587,1518844685871,26 -27588,1518844877340,25 -27589,1518844921477,24 -27590,1518845168509,24 -27591,1518845245375,23 -27592,1518845286733,23 -27593,1518845370873,23 -27594,1518845688864,25 -27595,1518845713848,23 -27596,1518845761346,25 -27597,1518845846665,25 -27598,1518845933853,24 -27599,1518846073420,24 -27600,1518846292655,23 -27601,1518846350265,22 -27602,1518846515401,22 -27603,1518846524741,22 -27604,1518846591972,27 -27605,1518846720561,27 -27606,1518846771451,26 -27607,1518846807219,26 -27608,1518846973460,27 -27609,1518847183829,26 -27610,1518847273560,25 -27611,1518847419673,25 -27612,1518847454392,23 -27613,1518847467752,25 -27614,1518847587684,28 -27615,1518847776684,28 -27616,1518847805758,27 -27617,1518847848549,28 -27618,1518847959760,29 -27619,1518848072331,29 -27620,1518848168183,28 -27621,1518848222834,28 -27622,1518848296366,27 -27623,1518848417727,28 -27624,1518848705566,26 -27625,1518848766461,27 -27626,1518848818207,26 -27627,1518848846136,26 -27628,1518848971946,27 -27629,1518849024287,27 -27630,1518849141371,28 -27631,1518849257544,27 -27632,1518849348166,27 -27633,1518849422738,26 -27634,1518849485782,26 -27635,1518849615779,25 -27636,1518849676060,24 -27637,1518849719479,24 -27638,1518849773957,24 -27639,1518849817158,25 -27640,1518849864502,25 -27641,1518849886044,25 -27642,1518849996758,26 -27643,1518850041029,26 -27644,1518850136117,26 -27645,1518850258699,26 -27646,1518850595422,24 -27647,1518850653317,23 -27648,1518850703098,23 -27649,1518850733062,24 -27650,1518850860913,24 -27651,1518850941015,23 -27652,1518851063523,22 -27653,1518851192613,22 -27654,1518851221536,22 -27655,1518851276972,22 -27656,1518851362236,22 -27657,1518851467253,21 -27658,1518851510364,22 -27659,1518851651102,24 -27660,1518851691345,24 -27661,1518851900234,24 -27662,1518851987451,24 -27663,1518852089621,23 -27664,1518852110117,22 -27665,1518852145844,25 -27666,1518852272159,26 -27667,1518852406195,25 -27668,1518852456816,24 -27669,1518852532493,24 -27670,1518852676636,24 -27671,1518966225749,23 -27672,1519054219917,23 -27673,1519054265359,22 -27674,1519054328227,22 -27675,1519060660130,23 -27676,1519060718394,21 -27677,1519060756142,22 -27678,1519060769655,22 -27679,1519060819294,24 -27680,1519060826868,25 -27681,1519061609515,31 -27682,1519061708877,30 -27683,1519150094042,31 -27684,1519151197715,29 -27685,1519151242624,28 -27686,1519151341918,28 -27687,1519151436925,28 -27688,1519151459319,27 -27689,1519151502660,28 -27690,1519204689045,28 -27691,1519204963896,27 -27692,1519205026583,27 -27693,1519205078733,26 -27694,1519205144329,26 -27695,1519205225055,25 -27696,1519205266575,25 -27697,1519205277638,27 -27698,1519205307150,32 -27699,1519205387904,32 -27700,1519205396055,32 -27701,1519205486184,40 -27702,1519205515467,39 -27703,1519205541691,41 -27704,1519535393216,45 -27705,1519536384281,45 -27706,1519633159123,43 -27707,1519633177491,41 -27708,1519633185172,46 -27709,1519633203372,59 -27710,1519633260702,64 -27711,1519633329449,65 -27712,1519633371735,65 -27713,1519633381675,68 -27714,1519633473078,84 -27715,1519633519907,84 -27716,1519634652916,86 -27717,1519634859342,84 -27718,1519635323377,84 -27719,1519635488953,83 -27720,1519635532119,81 -27721,1519635760809,84 -27722,1519637013374,83 -27723,1519637040785,80 -27724,1519637141739,85 -27725,1519637301112,85 -27726,1519637377546,83 -27727,1519639077778,84 -27728,1519639142787,83 -27729,1519639234133,83 -27730,1519639242160,84 -27731,1519641354966,106 -27732,1519641470321,104 -27733,1519641661342,102 -27734,1519641901585,102 -27735,1519641927837,100 -27736,1519642010020,106 -27737,1519642120980,106 -27738,1519642303415,106 -27739,1519642327431,105 -27740,1519642341752,112 -27741,1519642361141,128 -27742,1519642540359,142 -27743,1519642634931,140 -27744,1519642717785,141 -27745,1519643364499,141 -27746,1519643480894,138 -27747,1519643675231,136 -27748,1519643783885,135 -27749,1519643829052,134 -27750,1519643970640,138 -27751,1519644194478,137 -27752,1519644209270,134 -27753,1519644621458,152 -27754,1519644797274,148 -27755,1519645143186,147 -27756,1519645205373,144 -27757,1519645288886,145 -27758,1519645604267,145 -27759,1519645861782,142 -27760,1519646032168,139 -27761,1519646260585,137 -27762,1519646399259,134 -27763,1519646600416,132 -27764,1519646615368,128 -27765,1519646706855,146 -27766,1519647009535,145 -27767,1519647048580,141 -27768,1519647122873,145 -27769,1519647228884,145 -27770,1519647280879,144 -27771,1519647396398,146 -27772,1519647461235,143 -27773,1519647720294,143 -27774,1519648048716,140 -27775,1519648197306,135 -27776,1519648463741,131 -27777,1519648536938,128 -27778,1519648638622,127 -27779,1519648735902,127 -27780,1519649183745,125 -27781,1519649394887,124 -27782,1519649660138,119 -27783,1519649760537,116 -27784,1519649870430,112 -27785,1519649963367,109 -27786,1519650106521,108 -27787,1519650187440,104 -27788,1519650228670,102 -27789,1519650250990,104 -27790,1519650389318,110 -27791,1519650426027,106 -27792,1519650482049,107 -27793,1519650586166,106 -27794,1519650654530,103 -27795,1519650722711,101 -27796,1519650747251,99 -27797,1519650846972,103 -27798,1519650881224,102 -27799,1519650988152,105 -27800,1519651353478,101 -27801,1519651489180,101 -27802,1519651688098,97 -27803,1519651773495,94 -27804,1519651898726,91 -27805,1519652177166,87 -27806,1519652192291,81 -27807,1519652328117,89 -27808,1519652718334,86 -27809,1519652735619,88 -27810,1519652760398,98 -27811,1519652790151,102 -27812,1519652819880,106 -27813,1519652899164,109 -27814,1519653128746,115 -27815,1519653162848,111 -27816,1519653313006,115 -27817,1519653383624,110 -27818,1519653841652,108 -27819,1519653916851,103 -27820,1519653936604,100 -27821,1519654111486,109 -27822,1519654404458,103 -27823,1519654491392,98 -27824,1519654530780,98 -27825,1519654610870,98 -27826,1519654645203,95 -27827,1519654723104,97 -27828,1519654811682,93 -27829,1519654885357,91 -27830,1519655016688,88 -27831,1519655142268,96 -27832,1519655151992,92 -27833,1519655167125,109 -27834,1519655233220,120 -27835,1519655385647,118 -27836,1519655596309,119 -27837,1519655647840,114 -27838,1519655851462,114 -27839,1519655941800,109 -27840,1519656065215,110 -27841,1519656072967,115 -27842,1519656094912,153 -27843,1519656380542,164 -27844,1519656771945,160 -27845,1519657048064,157 -27846,1519657085104,150 -27847,1519657198548,155 -27848,1519657265466,152 -27849,1519657471166,152 -27850,1519658070751,150 -27851,1519658213544,145 -27852,1519658319756,142 -27853,1519659370999,149 -27854,1519659388477,142 -27855,1519659769392,156 -27856,1519659885171,151 -27857,1519659895221,150 -27858,1519660049375,181 -27859,1519660150217,177 -27860,1519660213661,174 -27861,1519660357419,175 -27862,1519660730256,170 -27863,1519660853304,166 -27864,1519661023318,161 -27865,1519661419046,167 -27866,1519662087792,163 -27867,1519662238908,156 -27868,1519662248875,156 -27869,1519662307360,189 -27870,1519662331807,191 -27871,1519662544959,205 -27872,1519662577233,201 -27873,1519663060958,211 -27874,1519663327937,204 -27875,1519663410645,198 -27876,1519663876050,197 -27877,1519664053656,191 -27878,1519664427861,188 -27879,1519664709548,183 -27880,1519664874591,177 -27881,1519664897261,172 -27882,1519665094242,183 -27883,1519665228582,178 -27884,1519665245819,174 -27885,1519665386967,191 -27886,1519665802864,186 -27887,1519666150991,180 -27888,1519666246167,175 -27889,1519666799833,173 -27890,1519666827253,171 -27891,1519667159887,179 -27892,1519667301179,175 -27893,1519667583089,172 -27894,1519667690828,166 -27895,1519667710535,163 -27896,1519667944167,176 -27897,1519668014605,174 -27898,1519668986677,172 -27899,1519669091209,168 -27900,1519669490733,165 -27901,1519670119100,157 -27902,1519670210992,149 -27903,1519670465745,146 -27904,1519670548836,140 -27905,1519670641300,136 -27906,1519670687986,131 -27907,1519670899930,136 -27908,1519670953904,129 -27909,1519671177396,127 -27910,1519671986053,126 -27911,1519672034679,123 -27912,1519672309137,124 -27913,1519672780369,122 -27914,1519672788034,115 -27915,1519673136253,144 -27916,1519673357094,140 -27917,1519673460991,134 -27918,1519673558499,130 -27919,1519673699769,125 -27920,1519673853709,120 -27921,1519673876092,120 -27922,1519674024417,125 -27923,1519674206834,119 -27924,1519674258119,113 -27925,1519674300531,113 -27926,1519674362461,112 -27927,1519674391725,111 -27928,1519674500765,113 -27929,1519674686374,107 -27930,1519675178406,102 -27931,1519675394448,95 -27932,1519675402024,88 -27933,1519675842127,119 -27934,1519675956015,119 -27935,1519676294272,116 -27936,1519676574311,108 -27937,1519676611491,102 -27938,1519676725718,103 -27939,1519676925104,97 -27940,1519677041662,91 -27941,1519677142958,86 -27942,1519677513717,97 -27943,1519677986127,98 -27944,1519678164830,92 -27945,1519678174806,86 -27946,1519678216610,99 -27947,1519678299050,102 -27948,1519678321444,99 -27949,1519678527968,104 -27950,1519678559717,98 -27951,1519678764768,98 -27952,1519678869460,93 -27953,1519678881862,88 -27954,1519679351501,98 -27955,1519679504691,99 -27956,1519679565652,93 -27957,1519679575649,91 -27958,1519679664080,123 -27959,1519679671578,120 -27960,1519680191417,152 -27961,1519680332191,148 -27962,1519680496718,144 -27963,1519680721136,138 -27964,1519680857546,133 -27965,1519681152823,128 -27966,1519681254374,122 -27967,1519681524405,116 -27968,1519681680294,111 -27969,1519681756131,123 -27970,1519682081536,123 -27971,1519682334615,127 -27972,1519682369573,122 -27973,1519682858604,130 -27974,1519682885675,123 -27975,1519683962625,128 -27976,1519684074283,124 -27977,1519684145226,120 -27978,1519684387968,117 -27979,1519684445009,112 -27980,1519684686487,110 -27981,1519684875877,105 -27982,1519684897933,109 -27983,1519685063486,115 -27984,1519685175029,110 -27985,1519685469316,118 -27986,1519685574085,113 -27987,1519685837474,109 -27988,1519686167439,105 -27989,1519686328072,100 -27990,1519686343273,95 -27991,1519686447129,111 -27992,1519686473988,108 -27993,1519686652331,111 -27994,1519686983104,107 -27995,1519687078080,103 -27996,1519687085596,108 -27997,1519687103400,137 -27998,1519687113301,151 -27999,1519687549910,181 -28000,1519687717883,176 -28001,1519687939753,170 -28002,1519688061797,164 -28003,1519688373480,162 -28004,1519688761726,156 -28005,1519689385387,151 -28006,1519689698742,146 -28007,1519689832390,142 -28008,1519690003415,138 -28009,1519690168576,135 -28010,1519690376763,130 -28011,1519690795320,124 -28012,1519690886144,120 -28013,1519691146445,116 -28014,1519691395200,110 -28015,1519691453848,121 -28016,1519691491145,120 -28017,1519691498630,121 -28018,1519691639693,154 -28019,1519691795438,150 -28020,1519692080282,146 -28021,1519692195498,141 -28022,1519692304342,142 -28023,1519692547306,138 -28024,1519692562176,133 -28025,1519692669610,150 -28026,1519692810942,148 -28027,1519692908101,145 -28028,1519692972704,145 -28029,1519693357342,144 -28030,1519693721950,137 -28031,1519693894085,131 -28032,1519694293167,126 -28033,1519694329944,133 -28034,1519694444754,134 -28035,1519694464419,130 -28036,1519694548812,140 -28037,1519694612364,136 -28038,1519694622295,136 -28039,1519694827413,163 -28040,1519695031899,157 -28041,1519695118431,152 -28042,1519695150340,149 -28043,1519695165095,152 -28044,1519695420967,168 -28045,1519695627090,161 -28046,1519695646768,165 -28047,1519695987177,180 -28048,1519696021460,173 -28049,1519696172129,182 -28050,1519696248513,178 -28051,1519696542800,178 -28052,1519696667277,171 -28053,1519697399947,167 -28054,1519697432324,167 -28055,1519697500809,171 -28056,1519697589817,169 -28057,1519697745720,166 -28058,1519698140183,172 -28059,1519698201379,166 -28060,1519698216327,183 -28061,1519698573890,205 -28062,1519698850911,200 -28063,1519698965171,193 -28064,1519699019063,190 -28065,1519699730519,191 -28066,1519699872786,184 -28067,1519699892730,180 -28068,1519699976056,193 -28069,1519700623452,192 -28070,1519700669961,185 -28071,1519700949692,186 -28072,1519701161820,180 -28073,1519701191167,177 -28074,1519701285533,183 -28075,1519701349885,184 -28076,1519701384010,181 -28077,1519701555266,186 -28078,1519701653237,181 -28079,1519701727858,178 -28080,1519702463580,176 -28081,1519702517206,168 -28082,1519702874512,167 -28083,1519702889543,165 -28084,1519703540321,183 -28085,1519703648765,175 -28086,1519703809881,170 -28087,1519703827268,164 -28088,1519704049102,178 -28089,1519704642346,169 -28090,1519705227240,161 -28091,1519705237221,160 -28092,1519705286702,189 -28093,1519705433180,193 -28094,1519705682262,187 -28095,1519705914203,179 -28096,1519705965645,172 -28097,1519706066071,187 -28098,1519706157533,191 -28099,1519706876381,206 -28100,1519707199358,197 -28101,1519707445231,191 -28102,1519707495093,185 -28103,1519707556703,186 -28104,1519707690804,185 -28105,1519707805167,179 -28106,1519707909182,174 -28107,1519708084190,169 -28108,1519708188814,162 -28109,1519708286250,157 -28110,1519708440002,153 -28111,1519709019874,147 -28112,1519709430198,138 -28113,1519709760966,131 -28114,1519709810022,123 -28115,1519710128027,119 -28116,1519710155190,113 -28117,1519710182519,118 -28118,1519710521542,138 -28119,1519710608898,131 -28120,1519710705934,127 -28121,1519710750731,121 -28122,1519710773093,120 -28123,1519710817103,126 -28124,1519711085928,124 -28125,1519711239670,127 -28126,1519711737523,121 -28127,1519711825519,114 -28128,1519711950010,109 -28129,1519712003912,106 -28130,1519712579474,102 -28131,1519712643737,93 -28132,1519712658640,88 -28133,1519712705627,94 -28134,1519713001747,94 -28135,1519713101785,87 -28136,1519713131135,88 -28137,1519713248212,88 -28138,1519713270551,84 -28139,1519713367444,100 -28140,1519713484512,95 -28141,1519713596712,89 -28142,1519713690722,85 -28143,1519713735428,84 -28144,1519713918090,93 -28145,1519713999372,87 -28146,1519714034141,81 -28147,1519714177592,90 -28148,1519714214512,84 -28149,1519714243943,87 -28150,1519714372849,88 -28151,1519714441381,84 -28152,1519714524478,80 -28153,1519715084409,77 -28154,1519715113892,70 -28155,1519715146658,73 -28156,1519715224388,74 -28157,1519715297013,70 -28158,1519715369336,66 -28159,1519715621217,61 -28160,1519715667854,57 -28161,1519715675580,68 -28162,1519715688070,82 -28163,1519715700515,92 -28164,1519715922086,103 -28165,1519716018424,101 -28166,1519716035966,96 -28167,1519716220838,102 -28168,1519716301124,107 -28169,1519716427626,105 -28170,1519716435300,100 -28171,1519716476601,128 -28172,1519716890241,128 -28173,1519716931671,122 -28174,1519717049392,129 -28175,1519717104323,125 -28176,1519717330707,126 -28177,1519717484458,126 -28178,1519717671167,122 -28179,1519717801078,118 -28180,1519717965242,115 -28181,1519717992018,109 -28182,1519718146276,115 -28183,1519718158639,110 -28184,1519718418613,137 -28185,1519718550461,131 -28186,1519719367929,128 -28187,1519719441275,122 -28188,1519719471325,130 -28189,1519719575929,133 -28190,1519719600908,129 -28191,1519719898322,135 -28192,1519719928219,148 -28193,1519720009095,157 -28194,1519721007201,157 -28195,1519721404291,150 -28196,1519721502584,146 -28197,1519721646340,146 -28198,1519721831976,144 -28199,1519721854412,141 -28200,1519722089613,149 -28201,1519722334803,144 -28202,1519722351880,140 -28203,1519722513431,156 -28204,1519722618108,155 -28205,1519722867030,153 -28206,1519722914292,149 -28207,1519723344895,152 -28208,1519723355004,146 -28209,1519723529953,175 -28210,1519723970014,171 -28211,1519724943223,166 -28212,1519724958215,159 -28213,1519725040409,177 -28214,1519725570547,175 -28215,1519725751402,170 -28216,1519726111049,165 -28217,1519726163232,163 -28218,1519726175664,168 -28219,1519726633024,193 -28220,1519726816104,188 -28221,1519726848163,184 -28222,1519727286858,191 -28223,1519727454800,191 -28224,1519727653632,189 -28225,1519727984834,184 -28226,1519728038374,178 -28227,1519728046054,178 -28228,1519728245377,227 -28229,1519728511084,222 -28230,1519728719444,216 -28231,1519729339615,210 -28232,1519730240390,204 -28233,1519730446930,202 -28234,1519730804092,198 -28235,1519731683585,191 -28236,1519731772372,184 -28237,1519732239383,183 -28238,1519732273480,176 -28239,1519732329962,184 -28240,1519732400968,185 -28241,1519732792526,183 -28242,1519733018153,177 -28243,1519733297084,170 -28244,1519734007331,165 -28245,1519734214478,157 -28246,1519734317348,152 -28247,1519734487880,149 -28248,1519734539077,143 -28249,1519734634342,144 -28250,1519734931001,142 -28251,1519735051533,135 -28252,1519735353012,130 -28253,1519735424558,123 -28254,1519735551680,119 -28255,1519735564054,116 -28256,1519735603574,132 -28257,1519735621156,132 -28258,1519735968634,142 -28259,1519736635189,135 -28260,1519736704543,126 -28261,1519736909810,123 -28262,1519736924686,125 -28263,1519737398416,144 -28264,1519737844196,146 -28265,1519738050672,138 -28266,1519738375266,132 -28267,1519738405213,130 -28268,1519738544093,133 -28269,1519738551568,128 -28270,1519738564019,161 -28271,1519738668989,199 -28272,1519738778607,197 -28273,1519738997541,192 -28274,1519739075669,189 -28275,1519739251450,187 -28276,1519739366015,182 -28277,1519739680989,178 -28278,1519739814663,171 -28279,1519739968924,166 -28280,1519740499654,159 -28281,1519740633267,152 -28282,1519740809036,150 -28283,1519741003024,143 -28284,1519741297980,147 -28285,1519741409657,139 -28286,1519741487868,135 -28287,1519741505408,130 -28288,1519741559706,141 -28289,1519741800806,143 -28290,1519742155271,137 -28291,1519742222305,135 -28292,1519742308633,131 -28293,1519742366311,132 -28294,1519742449130,131 -28295,1519742500291,126 -28296,1519742745057,124 -28297,1519742783856,118 -28298,1519742803660,116 -28299,1519742953146,122 -28300,1519743193725,122 -28301,1519743336530,116 -28302,1519743378305,109 -28303,1519743511250,116 -28304,1519743543988,110 -28305,1519743586100,112 -28306,1519743707055,110 -28307,1519743744178,107 -28308,1519743823887,105 -28309,1519743925202,117 -28310,1519744401838,112 -28311,1519744705534,105 -28312,1519744753109,97 -28313,1519744913618,106 -28314,1519744940777,103 -28315,1519745050320,104 -28316,1519745120261,99 -28317,1519745253598,94 -28318,1519745261077,92 -28319,1519745673565,129 -28320,1519745878057,123 -28321,1519746106871,117 -28322,1519746276847,116 -28323,1519746292181,111 -28324,1519746511992,122 -28325,1519746627610,116 -28326,1519746686843,111 -28327,1519746704306,111 -28328,1519746714411,146 -28329,1519746985502,175 -28330,1519747611085,169 -28331,1519748010993,164 -28332,1519748188105,157 -28333,1519748217818,151 -28334,1519748334031,157 -28335,1519748704611,151 -28336,1519749057635,145 -28337,1519749458823,140 -28338,1519749956386,134 -28339,1519750193074,131 -28340,1519750225310,129 -28341,1519750397492,134 -28342,1519750466996,128 -28343,1519750476961,125 -28344,1519750508843,148 -28345,1519750573138,151 -28346,1519750697876,149 -28347,1519750727951,145 -28348,1519750743103,149 -28349,1519750915815,168 -28350,1519750955450,163 -28351,1519751010081,163 -28352,1519751022456,164 -28353,1519751091769,186 -28354,1519751358147,185 -28355,1519751439703,178 -28356,1519751906747,185 -28357,1519752138525,180 -28358,1519752763189,182 -28359,1519752829701,174 -28360,1519753028375,172 -28361,1519753157497,166 -28362,1519753190110,162 -28363,1519753613132,174 -28364,1519753704478,167 -28365,1519753778312,162 -28366,1519753898939,159 -28367,1519753943840,153 -28368,1519753973922,158 -28369,1519754035646,163 -28370,1519754109588,180 -28371,1519754242323,194 -28372,1519754891532,191 -28373,1519754904020,185 -28374,1519755480311,214 -28375,1519755535361,209 -28376,1519755666700,210 -28377,1519756059424,207 -28378,1519756099329,200 -28379,1519756914735,205 -28380,1519756939390,198 -28381,1519757485126,208 -28382,1519757714454,201 -28383,1519757726970,194 -28384,1519757931458,224 -28385,1519757978299,217 -28386,1519758155898,220 -28387,1519758378208,215 -28388,1519758506096,216 -28389,1519758523716,214 -28390,1519759294782,235 -28391,1519759882951,226 -28392,1519760126544,218 -28393,1519760283890,213 -28394,1519760419534,209 -28395,1519760540358,204 -28396,1519760717210,201 -28397,1519761345559,195 -28398,1519761675412,189 -28399,1519761762053,188 -28400,1519762006306,185 -28401,1519762513812,177 -28402,1519762965282,169 -28403,1519763160077,164 -28404,1519763255465,157 -28405,1519763347598,156 -28406,1519763513432,153 -28407,1519763734836,146 -28408,1519763744847,142 -28409,1519763779645,169 -28410,1519763853418,172 -28411,1519763909949,168 -28412,1519764320570,165 -28413,1519764797115,158 -28414,1519765379919,150 -28415,1519765451531,145 -28416,1519765641142,141 -28417,1519765749399,134 -28418,1519765880056,128 -28419,1519766123708,136 -28420,1519766335039,128 -28421,1519766406488,120 -28422,1519766480705,114 -28423,1519766673415,109 -28424,1519767629963,110 -28425,1519767784896,101 -28426,1519768159969,95 -28427,1519768465481,89 -28428,1519768586535,88 -28429,1519768672994,97 -28430,1519768801004,92 -28431,1519769042712,86 -28432,1519769082057,78 -28433,1519769141469,75 -28434,1519769282229,76 -28435,1519769356327,70 -28436,1519769405803,64 -28437,1519769413452,59 -28438,1519769426101,70 -28439,1519769502081,74 -28440,1519769679737,68 -28441,1519769714394,65 -28442,1519769843053,61 -28443,1519769895190,56 -28444,1519769905104,65 -28445,1519769932732,78 -28446,1519769950134,79 -28447,1519770014466,83 -28448,1519770027325,82 -28449,1519770049936,102 -28450,1519770079557,105 -28451,1519770097045,110 -28452,1519770201358,121 -28453,1519770266457,131 -28454,1519770398770,130 -28455,1519770550939,125 -28456,1519770566313,122 -28457,1519770618601,133 -28458,1519771279471,132 -28459,1519771405101,124 -28460,1519771454579,120 -28461,1519771509296,119 -28462,1519771584211,117 -28463,1519771739061,119 -28464,1519771943184,112 -28465,1519772103137,107 -28466,1519772191221,104 -28467,1519772206275,99 -28468,1519772346873,110 -28469,1519772354591,111 -28470,1519772512443,140 -28471,1519772532552,136 -28472,1519772600467,145 -28473,1519772770644,143 -28474,1519773297838,153 -28475,1519773312696,146 -28476,1519773433330,166 -28477,1519773488040,163 -28478,1519773675325,162 -28479,1519773762380,161 -28480,1519774292263,157 -28481,1519774772821,159 -28482,1519775102490,152 -28483,1519775281260,146 -28484,1519776623110,159 -28485,1519776766307,153 -28486,1519776959584,153 -28487,1519777511616,149 -28488,1519778072639,143 -28489,1519778144417,138 -28490,1519778390603,150 -28491,1519778418240,145 -28492,1519778974305,151 -28493,1519779075347,145 -28494,1519779144350,142 -28495,1519779458950,141 -28496,1519779594427,137 -28497,1519779641445,134 -28498,1519780158180,134 -28499,1519780266540,128 -28500,1519780291151,126 -28501,1519780840206,132 -28502,1519780870222,125 -28503,1519781136092,128 -28504,1519781268767,123 -28505,1519781475389,119 -28506,1519781492756,115 -28507,1519781616417,124 -28508,1519781650826,120 -28509,1519781826438,138 -28510,1519781851599,138 -28511,1519782263259,147 -28512,1519782280654,144 -28513,1519782436248,157 -28514,1519782495557,152 -28515,1519782530244,151 -28516,1519782616713,156 -28517,1519782802147,154 -28518,1519783014761,149 -28519,1519783074711,144 -28520,1519783338332,143 -28521,1519783353267,138 -28522,1519783407765,154 -28523,1519783450267,154 -28524,1519783548791,155 -28525,1519783622080,151 -28526,1519783667330,149 -28527,1519784026580,148 -28528,1519784122955,141 -28529,1519784350967,137 -28530,1519784358299,131 -28531,1519784650252,166 -28532,1519784863068,158 -28533,1519785023819,154 -28534,1519785238374,149 -28535,1519785315172,142 -28536,1519785337377,138 -28537,1519785399541,146 -28538,1519785513103,152 -28539,1519785839549,152 -28540,1519785847121,146 -28541,1519786278563,183 -28542,1519786659893,177 -28543,1519786719478,169 -28544,1519786882790,168 -28545,1519787098353,168 -28546,1519787132877,164 -28547,1519787650204,172 -28548,1519787818242,165 -28549,1519788191292,166 -28550,1519788199125,163 -28551,1519788317456,208 -28552,1519788837688,211 -28553,1519789529373,204 -28554,1519789643338,197 -28555,1519790034294,194 -28556,1519790061525,187 -28557,1519790086531,204 -28558,1519790096718,217 -28559,1519790202748,258 -28560,1519790726551,256 -28561,1519791104589,249 -28562,1519791182538,243 -28563,1519791532314,242 -28564,1519791589335,234 -28565,1519791958825,234 -28566,1519792536124,227 -28567,1519793103071,219 -28568,1519793240505,217 -28569,1519793250597,211 -28570,1519793394412,270 -28571,1519793404298,264 -28572,1519793611264,326 -28573,1519793927518,321 -28574,1519794098135,314 -28575,1519794452524,307 -28576,1519794995065,311 -28577,1519795156780,303 -28578,1519795228267,300 -28579,1519795255750,300 -28580,1519796385169,318 -28581,1519796437458,307 -28582,1519796492531,310 -28583,1519797152555,313 -28584,1519797283198,304 -28585,1519797557697,298 -28586,1519797688209,290 -28587,1519797705605,284 -28588,1519798046093,311 -28589,1519798228509,302 -28590,1519798398470,296 -28591,1519798763257,288 -28592,1519798822587,284 -28593,1519798941343,284 -28594,1519798971884,279 -28595,1519799549215,291 -28596,1519799719582,279 -28597,1519799978596,272 -28598,1519800040477,266 -28599,1519800357813,263 -28600,1519800725346,253 -28601,1519800774364,248 -28602,1519800809981,248 -28603,1519800997532,258 -28604,1519801066724,248 -28605,1519801267122,245 -28606,1519801472017,235 -28607,1519801522358,233 -28608,1519801850554,232 -28609,1519801983873,225 -28610,1519802688401,218 -28611,1519802910971,213 -28612,1519804337901,202 -28613,1519804446436,200 -28614,1519804454170,194 -28615,1519804718652,244 -28616,1519804948194,238 -28617,1519804965718,230 -28618,1519805357957,249 -28619,1519806012075,238 -28620,1519806111119,228 -28621,1519806295879,220 -28622,1519806752675,221 -28623,1519806974483,212 -28624,1519807067166,206 -28625,1519807811724,201 -28626,1519808661938,190 -28627,1519808822522,182 -28628,1519809249688,171 -28629,1519809378155,161 -28630,1519809484570,152 -28631,1519809514334,165 -28632,1519810375415,166 -28633,1519810398044,155 -28634,1519810423156,160 -28635,1519810451187,163 -28636,1519810797028,167 -28637,1519810827043,162 -28638,1519810877170,165 -28639,1519811017864,161 -28640,1519811333758,152 -28641,1519811769315,163 -28642,1519812358592,153 -28643,1519812856292,141 -28644,1519812915596,133 -28645,1519813026598,127 -28646,1519813457754,118 -28647,1519813554215,112 -28648,1519813767881,104 -28649,1519814237881,94 -28650,1519814250465,82 -28651,1519814377127,111 -28652,1519814446602,103 -28653,1519814495321,96 -28654,1519814574542,89 -28655,1519814682364,82 -28656,1519814877821,73 -28657,1519814988113,71 -28658,1519814997885,71 -28659,1519815045958,103 -28660,1519815299507,100 -28661,1519815309429,91 -28662,1519815436161,103 -28663,1519815622438,98 -28664,1519815646781,89 -28665,1519815661284,91 -28666,1519815733550,97 -28667,1519815750739,89 -28668,1519815813097,91 -28669,1519815822997,85 -28670,1519815881028,120 -28671,1519815955319,117 -28672,1519816037224,142 -28673,1519816071074,138 -28674,1519816250262,140 -28675,1519816413008,133 -28676,1519816619425,126 -28677,1519816753399,118 -28678,1519816991581,113 -28679,1519817082745,108 -28680,1519817195247,115 -28681,1519817214635,108 -28682,1519817286533,119 -28683,1519817336896,121 -28684,1519817626194,117 -28685,1519817723043,112 -28686,1519817814202,106 -28687,1519817872236,103 -28688,1519817945034,118 -28689,1519818198175,113 -28690,1519818643171,108 -28691,1519818735382,101 -28692,1519818759816,96 -28693,1519818942879,103 -28694,1519819054634,99 -28695,1519819244968,103 -28696,1519819266986,96 -28697,1519819296125,100 -28698,1519819371824,101 -28699,1519819486344,102 -28700,1519819506046,96 -28701,1519819857484,100 -28702,1519820018677,98 -28703,1519820045724,100 -28704,1519820063134,102 -28705,1519820145167,112 -28706,1519820407581,109 -28707,1519820483342,103 -28708,1519820979992,103 -28709,1519821105431,96 -28710,1519821120327,91 -28711,1519821152040,98 -28712,1519821239732,99 -28713,1519821775611,93 -28714,1519821836443,87 -28715,1519822044817,113 -28716,1519822131863,108 -28717,1519822272004,104 -28718,1519822323395,115 -28719,1519822347684,113 -28720,1519822530950,118 -28721,1519822625432,115 -28722,1519822836853,112 -28723,1519823350200,107 -28724,1519823701038,101 -28725,1519823725479,97 -28726,1519823829498,100 -28727,1519823837064,94 -28728,1519823864223,119 -28729,1519823987286,122 -28730,1519824294009,117 -28731,1519824301638,113 -28732,1519824510233,147 -28733,1519824527661,141 -28734,1519824678194,161 -28735,1519824808561,162 -28736,1519825037003,164 -28737,1519825078389,159 -28738,1519825187262,166 -28739,1519825194758,166 -28740,1519825321691,214 -28741,1519825841142,209 -28742,1519826150240,202 -28743,1519826463274,195 -28744,1519826638686,188 -28745,1519826682314,186 -28746,1519826782442,188 -28747,1519827051595,184 -28748,1519827119854,178 -28749,1519827132267,177 -28750,1519827323158,202 -28751,1519827614897,204 -28752,1519827773963,197 -28753,1519827784002,192 -28754,1519828046204,231 -28755,1519828114508,226 -28756,1519828552491,224 -28757,1519828576861,217 -28758,1519829035887,229 -28759,1519829205580,228 -28760,1519829453455,224 -28761,1519829643411,217 -28762,1519829699311,221 -28763,1519829818188,222 -28764,1519830382364,218 -28765,1519830401939,213 -28766,1519830601351,237 -28767,1519830637706,232 -28768,1519830793997,244 -28769,1519831118858,240 -28770,1519831257537,242 -28771,1519831445700,239 -28772,1519832301529,234 -28773,1519832529673,227 -28774,1519832830543,226 -28775,1519832850076,219 -28776,1519833307254,237 -28777,1519833341635,229 -28778,1519833653053,237 -28779,1519833731690,229 -28780,1519834008738,228 -28781,1519834157129,221 -28782,1519834928289,221 -28783,1519835005841,214 -28784,1519835173520,214 -28785,1519835646003,208 -28786,1519835896812,200 -28787,1519836035487,194 -28788,1519836295280,189 -28789,1519836633162,183 -28790,1519836745593,175 -28791,1519836806370,169 -28792,1519836845476,168 -28793,1519837411158,173 -28794,1519837751790,164 -28795,1519838096697,156 -28796,1519838673523,148 -28797,1519838709997,145 -28798,1519838931247,148 -28799,1519839038525,142 -28800,1519839263907,136 -28801,1519839455943,134 -28802,1519839595274,127 -28803,1519839812213,119 -28804,1519840039512,115 -28805,1519840137108,115 -28806,1519840531739,109 -28807,1519840650139,101 -28808,1519840819977,96 -28809,1519840858777,88 -28810,1519840963098,86 -28811,1519841203743,85 -28812,1519841233289,81 -28813,1519841460133,80 -28814,1519841467686,72 -28815,1519841502256,88 -28816,1519841553588,85 -28817,1519841657572,80 -28818,1519841677584,74 -28819,1519841706852,75 -28820,1519841743793,78 -28821,1519841763523,74 -28822,1519841867805,76 -28823,1519842052028,68 -28824,1519842088634,60 -28825,1519842178287,55 -28826,1519842255639,51 -28827,1519842301675,44 -28828,1519842394189,52 -28829,1519842406514,49 -28830,1519842448107,52 -28831,1519842640248,46 -28832,1519842802786,55 -28833,1519842863707,49 -28834,1519842960538,52 -28835,1519843185778,46 -28836,1519843203172,40 -28837,1519843213113,38 -28838,1519843240242,44 -28839,1519843247731,41 -28840,1519843371466,72 -28841,1519843426700,68 -28842,1519843473087,64 -28843,1519843544099,60 -28844,1519843612681,55 -28845,1519843837980,51 -28846,1519843891445,49 -28847,1519843937846,46 -28848,1519844049116,41 -28849,1519844178264,38 -28850,1519844238943,49 -28851,1519844275291,45 -28852,1519844367355,41 -28853,1519844408755,37 -28854,1519844450348,57 -28855,1519844489390,54 -28856,1519844640849,56 -28857,1519844660630,50 -28858,1519844668111,61 -28859,1519844767553,75 -28860,1519844914905,72 -28861,1519845052491,68 -28862,1519845235297,65 -28863,1519845313794,64 -28864,1519845553586,62 -28865,1519845568402,58 -28866,1519845655859,74 -28867,1519845832040,72 -28868,1519845856794,74 -28869,1519845947366,78 -28870,1519846023059,75 -28871,1519846037804,74 -28872,1519846128082,82 -28873,1519846182080,79 -28874,1519846201754,78 -28875,1519846313110,83 -28876,1519846349399,92 -28877,1519846468337,94 -28878,1519846625340,98 -28879,1519846794892,95 -28880,1519847005072,95 -28881,1519847036875,92 -28882,1519847334482,94 -28883,1519847424151,90 -28884,1519847567788,91 -28885,1519847599599,88 -28886,1519847633752,91 -28887,1519847706789,92 -28888,1519847759993,92 -28889,1519847819113,92 -28890,1519847902318,91 -28891,1519847919743,89 -28892,1519847970650,100 -28893,1519847997817,104 -28894,1519848024734,109 -28895,1519848317960,113 -28896,1519848410096,109 -28897,1519848550632,106 -28898,1519848609342,107 -28899,1519848655815,107 -28900,1519848788268,108 -28901,1519848945920,105 -28902,1519849119747,101 -28903,1519849260398,99 -28904,1519849405653,95 -28905,1519849415985,92 -28906,1519849684819,108 -28907,1519850158084,104 -28908,1519850213734,99 -28909,1519850221578,99 -28910,1519850275812,126 -28911,1519850285710,126 -28912,1519850392167,151 -28913,1519851092128,150 -28914,1519851164812,144 -28915,1519851562543,154 -28916,1519851669714,151 -28917,1519851846280,151 -28918,1519852010966,147 -28919,1519852317237,147 -28920,1519852324690,145 -28921,1519852590656,188 -28922,1519853829833,187 -28923,1519855258866,181 -28924,1519855361164,176 -28925,1519855622742,175 -28926,1519856047875,170 -28927,1519856180733,165 -28928,1519856900818,163 -28929,1519857518198,157 -28930,1519857639239,156 -28931,1519858087391,153 -28932,1519858495302,148 -28933,1519858544039,142 -28934,1519858750037,144 -28935,1519858920946,140 -28936,1519859006466,135 -28937,1519859290087,135 -28938,1519859478072,134 -28939,1519859567642,131 -28940,1519859592278,135 -28941,1519859780470,142 -28942,1519859863068,138 -28943,1519860181024,138 -28944,1519860200790,133 -28945,1519860623377,144 -28946,1519861031385,138 -28947,1519861180249,133 -28948,1519861234281,130 -28949,1519861355335,129 -28950,1519861487281,125 -28951,1519862150605,121 -28952,1519862495742,117 -28953,1519862592600,111 -28954,1519862614987,107 -28955,1519862651356,114 -28956,1519862676098,117 -28957,1519862736914,121 -28958,1519863029608,122 -28959,1519863326193,126 -28960,1519863341166,121 -28961,1519863480222,133 -28962,1519863492630,130 -28963,1519863626364,147 -28964,1519863764263,144 -28965,1519863983906,139 -28966,1519864065929,137 -28967,1519864150175,135 -28968,1519864177457,133 -28969,1519864409262,140 -28970,1519865364777,135 -28971,1519865591189,129 -28972,1519865736073,129 -28973,1519866143069,125 -28974,1519866279188,120 -28975,1519866667753,119 -28976,1519866817579,113 -28977,1519866942314,111 -28978,1519866988804,107 -28979,1519867152856,106 -28980,1519867189505,101 -28981,1519867313220,101 -28982,1519867514887,99 -28983,1519867616747,93 -28984,1519867880390,90 -28985,1519867983440,83 -28986,1519868174159,82 -28987,1519868222733,79 -28988,1519868252437,77 -28989,1519868428687,79 -28990,1519868482112,74 -28991,1519868571919,72 -28992,1519868586494,73 -28993,1519868647215,81 -28994,1519868679207,81 -28995,1519868783266,86 -28996,1519868995357,80 -28997,1519869048990,76 -28998,1519869124962,74 -28999,1519869296682,72 -29000,1519869442779,68 -29001,1519869462463,63 -29002,1519869523175,65 -29003,1519869662150,62 -29004,1519869737478,56 -29005,1519869771626,52 -29006,1519869865710,59 -29007,1519869928468,55 -29008,1519870129169,51 -29009,1519870254883,47 -29010,1519870340072,57 -29011,1519870456374,55 -29012,1519870485522,66 -29013,1519870859010,67 -29014,1519870883665,62 -29015,1519871119085,65 -29016,1519871165277,60 -29017,1519871286458,59 -29018,1519871352627,56 -29019,1519871372286,53 -29020,1519871585198,55 -29021,1519871597594,73 -29022,1519871654122,84 -29023,1519871804904,82 -29024,1519872236824,78 -29025,1519872366669,75 -29026,1519872457091,71 -29027,1519872854612,69 -29028,1519872869322,66 -29029,1519872985582,71 -29030,1519873000626,67 -29031,1519873150764,74 -29032,1519873278865,71 -29033,1519873468507,66 -29034,1519873625282,66 -29035,1519874036738,62 -29036,1519874107118,58 -29037,1519874138883,57 -29038,1519874158591,56 -29039,1519874183078,58 -29040,1519874227148,59 -29041,1519874261314,64 -29042,1519874324801,64 -29043,1519874441571,64 -29044,1519874579451,60 -29045,1519874715624,64 -29046,1519875082253,60 -29047,1519875109097,55 -29048,1519875155347,57 -29049,1519875345607,57 -29050,1519875399316,53 -29051,1519875411644,52 -29052,1519875438393,58 -29053,1519875477291,58 -29054,1519875535218,57 -29055,1519875589639,60 -29056,1519875613890,61 -29057,1519875932818,68 -29058,1519875983550,65 -29059,1519876074323,64 -29060,1519876463845,62 -29061,1519876517469,66 -29062,1519876529860,66 -29063,1519876583390,87 -29064,1519876632187,88 -29065,1519876697992,88 -29066,1519876793666,87 -29067,1519876801497,87 -29068,1519876842832,111 -29069,1519876994585,118 -29070,1519877232879,116 -29071,1519877339933,112 -29072,1519877359553,111 -29073,1519877410570,120 -29074,1519877456915,121 -29075,1519877500807,123 -29076,1519877579197,125 -29077,1519877940994,124 -29078,1519878270981,121 -29079,1519878425350,119 -29080,1519878770274,117 -29081,1519878809302,116 -29082,1519879410950,119 -29083,1519879510118,114 -29084,1519879613764,113 -29085,1519879830805,111 -29086,1519879860214,107 -29087,1519879882372,111 -29088,1519880186222,120 -29089,1519880234961,119 -29090,1519880289064,119 -29091,1519880313238,121 -29092,1519880470618,128 -29093,1519880572649,131 -29094,1519880763511,130 -29095,1519880790358,129 -29096,1519881048988,136 -29097,1519881356481,132 -29098,1519881861912,129 -29099,1519881925149,125 -29100,1519882079455,125 -29101,1519882200398,121 -29102,1519882612455,123 -29103,1519882837264,119 -29104,1519883093423,115 -29105,1519883609319,111 -29106,1519883633825,108 -29107,1519883655736,114 -29108,1519883803664,122 -29109,1519883837745,118 -29110,1519884114965,121 -29111,1519884399047,117 -29112,1519884501473,112 -29113,1519884684054,112 -29114,1519884716043,108 -29115,1519884742968,113 -29116,1519884784061,118 -29117,1519885018683,120 -29118,1519885258785,116 -29119,1519885273639,112 -29120,1519885669568,127 -29121,1519885703751,122 -29122,1519885865483,132 -29123,1519885970261,129 -29124,1519886076969,127 -29125,1519886291195,123 -29126,1519886334933,119 -29127,1519886391017,120 -29128,1519886422696,119 -29129,1519886471936,128 -29130,1519886800833,128 -29131,1519887163230,128 -29132,1519887288011,123 -29133,1519887442983,120 -29134,1519887674972,116 -29135,1519887704466,111 -29136,1519887892766,114 -29137,1519888044985,110 -29138,1519888100763,107 -29139,1519888118226,109 -29140,1519888246330,120 -29141,1519888275613,118 -29142,1519888292727,123 -29143,1519888633618,136 -29144,1519888871868,131 -29145,1519888969269,125 -29146,1519889035306,122 -29147,1519889146684,120 -29148,1519889554733,118 -29149,1519889782078,114 -29150,1519890184664,108 -29151,1519890204467,103 -29152,1519890236328,114 -29153,1519890357859,119 -29154,1519890440226,116 -29155,1519890549587,112 -29156,1519890600425,110 -29157,1519890612924,112 -29158,1519890655344,127 -29159,1519890689233,128 -29160,1519890863217,131 -29161,1519891044556,126 -29162,1519891095282,120 -29163,1519891747873,126 -29164,1519891808201,121 -29165,1519891912324,121 -29166,1519892144783,118 -29167,1519892200607,114 -29168,1519892249837,125 -29169,1519892335115,128 -29170,1519892799467,126 -29171,1519892826380,119 -29172,1519892928195,125 -29173,1519893063807,127 -29174,1519893567926,126 -29175,1519893577641,123 -29176,1519893665323,150 -29177,1519893779946,149 -29178,1519893836058,145 -29179,1519894006435,145 -29180,1519894151025,141 -29181,1519894286732,137 -29182,1519894433013,135 -29183,1519894471906,131 -29184,1519894503665,133 -29185,1519894518572,137 -29186,1519894533785,152 -29187,1519894689416,173 -29188,1519894791523,174 -29189,1519895482144,170 -29190,1519895557202,167 -29191,1519895639561,167 -29192,1519895872204,170 -29193,1519896171636,165 -29194,1519896313143,161 -29195,1519896706655,156 -29196,1519896787304,156 -29197,1519897013520,154 -29198,1519897230604,148 -29199,1519897672734,143 -29200,1519897714022,138 -29201,1519898102910,140 -29202,1519898284683,135 -29203,1519898448790,129 -29204,1519898485466,124 -29205,1519898711880,125 -29206,1519898748830,119 -29207,1519898862297,124 -29208,1519898940568,126 -29209,1519899099843,123 -29210,1519899665978,122 -29211,1519899859549,116 -29212,1519900164755,110 -29213,1519900218588,105 -29214,1519900301424,102 -29215,1519900384774,103 -29216,1519900486271,104 -29217,1519900607622,102 -29218,1519900663675,98 -29219,1519900675834,96 -29220,1519900880760,116 -29221,1519901109948,110 -29222,1519901269826,109 -29223,1519901297067,105 -29224,1519901441995,108 -29225,1519901468621,104 -29226,1519901526705,107 -29227,1519902368801,107 -29228,1519902386068,102 -29229,1519902446681,114 -29230,1519902466158,115 -29231,1519902527055,123 -29232,1519902877168,120 -29233,1519903193395,115 -29234,1519903220174,108 -29235,1519903285612,111 -29236,1519903449728,112 -29237,1519903519769,107 -29238,1519903565922,104 -29239,1519903652815,105 -29240,1519903761388,107 -29241,1519903918882,103 -29242,1519904044509,102 -29243,1519904141498,106 -29244,1519904243362,102 -29245,1519904253410,98 -29246,1519904294688,116 -29247,1519904473616,117 -29248,1519904766276,113 -29249,1519904822029,107 -29250,1519904983766,105 -29251,1519905015402,99 -29252,1519905346071,105 -29253,1519905408895,103 -29254,1519905430830,101 -29255,1519905581117,106 -29256,1519905682823,102 -29257,1519905767909,99 -29258,1519905780290,106 -29259,1519905822157,123 -29260,1519905849489,127 -29261,1519905987875,133 -29262,1519906147797,127 -29263,1519906170196,125 -29264,1519906371176,132 -29265,1519906602711,128 -29266,1519906656488,123 -29267,1519906664364,121 -29268,1519907014145,153 -29269,1519907131630,149 -29270,1519907241119,146 -29271,1519907263185,142 -29272,1519907449147,155 -29273,1519907493383,150 -29274,1519907535354,151 -29275,1519907598794,152 -29276,1519907640801,165 -29277,1519908146895,169 -29278,1519908154307,163 -29279,1519908724984,212 -29280,1519908737382,204 -29281,1519909027079,237 -29282,1519909348073,230 -29283,1519909450999,224 -29284,1519909637994,224 -29285,1519909736296,224 -29286,1519909797939,231 -29287,1519910369037,244 -29288,1519910536585,238 -29289,1519910865357,235 -29290,1519911001683,228 -29291,1519911079705,226 -29292,1519911162755,227 -29293,1519911175445,226 -29294,1519911630907,261 -29295,1519911717125,254 -29296,1519912474060,252 -29297,1519912719641,247 -29298,1519913177919,241 -29299,1519913479667,233 -29300,1519913526688,226 -29301,1519913590970,232 -29302,1519914006522,232 -29303,1519914397381,225 -29304,1519915030567,218 -29305,1519915089677,213 -29306,1519915288919,213 -29307,1519915495991,210 -29308,1519915916722,205 -29309,1519915980266,198 -29310,1519916166983,197 -29311,1519916347303,191 -29312,1519916856036,184 -29313,1519917659494,177 -29314,1519917932729,170 -29315,1519918233560,163 -29316,1519918260584,157 -29317,1519918400588,163 -29318,1519918447763,157 -29319,1519918777993,158 -29320,1519919150540,159 -29321,1519919274129,151 -29322,1519919434710,146 -29323,1519919540950,140 -29324,1519919593094,138 -29325,1519919627997,136 -29326,1519919693087,140 -29327,1519919923884,139 -29328,1519919981117,131 -29329,1519920263122,134 -29330,1519920418432,129 -29331,1519920450777,129 -29332,1519920507440,132 -29333,1519920557403,129 -29334,1519920584735,126 -29335,1519920669284,133 -29336,1519920828957,129 -29337,1519920881472,123 -29338,1519921005654,122 -29339,1519921193516,117 -29340,1519921208598,111 -29341,1519921265868,121 -29342,1519921666564,117 -29343,1519921843951,109 -29344,1519921873708,103 -29345,1519922156168,102 -29346,1519922173505,106 -29347,1519922284745,115 -29348,1519922563185,109 -29349,1519922603040,101 -29350,1519922669648,100 -29351,1519922753548,95 -29352,1519922863207,92 -29353,1519923024461,85 -29354,1519923306962,79 -29355,1519923460296,76 -29356,1519923502477,69 -29357,1519923524863,66 -29358,1519923584493,65 -29359,1519923611589,69 -29360,1519923631338,69 -29361,1519923658422,75 -29362,1519923745207,73 -29363,1519923908548,68 -29364,1519923928593,66 -29365,1519924025403,67 -29366,1519924065081,60 -29367,1519924092342,57 -29368,1519924102265,72 -29369,1519924144213,82 -29370,1519924404002,80 -29371,1519924461307,73 -29372,1519924479158,76 -29373,1519924543556,79 -29374,1519924570942,77 -29375,1519924774056,80 -29376,1519924808815,75 -29377,1519924821155,77 -29378,1519925050212,85 -29379,1519925161867,104 -29380,1519925252057,98 -29381,1519925470452,114 -29382,1519925603954,109 -29383,1519925634089,104 -29384,1519925733940,109 -29385,1519926118407,105 -29386,1519926180300,101 -29387,1519926212972,103 -29388,1519926543700,104 -29389,1519926655512,99 -29390,1519926665721,95 -29391,1519926885359,113 -29392,1519927293143,110 -29393,1519927407181,107 -29394,1519927529541,124 -29395,1519927559502,120 -29396,1519927589477,127 -29397,1519927609403,131 -29398,1519927918293,140 -29399,1519928346337,135 -29400,1519928412355,131 -29401,1519928494052,134 -29402,1519928571161,136 -29403,1519928800722,133 -29404,1519928855183,128 -29405,1519928907182,128 -29406,1519929117548,132 -29407,1519929204685,127 -29408,1519929217222,125 -29409,1519929452192,143 -29410,1519929742475,141 -29411,1519929872335,136 -29412,1519929978961,133 -29413,1519930048502,129 -29414,1519930120254,127 -29415,1519930296383,124 -29416,1519930321616,120 -29417,1519930559439,131 -29418,1519930623893,126 -29419,1519930658571,128 -29420,1519930894894,130 -29421,1519930977348,124 -29422,1519931263949,123 -29423,1519931310868,118 -29424,1519931427923,118 -29425,1519931440157,116 -29426,1519931536293,136 -29427,1519931767346,134 -29428,1519931782491,130 -29429,1519931802355,146 -29430,1519932043868,156 -29431,1519932344497,151 -29432,1519932509320,149 -29433,1519932893209,146 -29434,1519932987263,143 -29435,1519932994798,145 -29436,1519933431561,185 -29437,1519933839967,179 -29438,1519933889670,174 -29439,1519934641362,176 -29440,1519934982231,170 -29441,1519935038746,171 -29442,1519935830590,174 -29443,1519935907672,167 -29444,1519936140374,164 -29445,1519936162545,162 -29446,1519936349278,172 -29447,1519936436824,174 -29448,1519936647834,172 -29449,1519936667944,167 -29450,1519936783282,181 -29451,1519936805923,179 -29452,1519937164334,190 -29453,1519937904026,185 -29454,1519938033685,178 -29455,1519938265132,173 -29456,1519938323340,166 -29457,1519938656753,166 -29458,1519938704541,163 -29459,1519938915987,164 -29460,1519939481130,160 -29461,1519939832860,157 -29462,1519939875509,153 -29463,1519939939744,154 -29464,1519940409047,152 -29465,1519940544122,149 -29466,1519940593925,143 -29467,1519941864093,144 -29468,1519941954385,138 -29469,1519942223865,143 -29470,1519942507207,139 -29471,1519942690191,132 -29472,1519942747705,127 -29473,1519942772893,129 -29474,1519942832250,135 -29475,1519943002712,136 -29476,1519943253269,130 -29477,1519943331920,126 -29478,1519943463016,129 -29479,1519943927536,124 -29480,1519944364369,118 -29481,1519944435251,113 -29482,1519944509676,109 -29483,1519944702395,106 -29484,1519944815887,103 -29485,1519945027888,99 -29486,1519945065042,92 -29487,1519945203461,93 -29488,1519945281606,91 -29489,1519945536611,86 -29490,1519945601302,80 -29491,1519945624622,86 -29492,1519945686668,89 -29493,1519945767166,85 -29494,1519945792179,80 -29495,1519946090234,82 -29496,1519946140161,80 -29497,1519946246543,82 -29498,1519946440841,84 -29499,1519946448388,78 -29500,1519946607686,96 -29501,1519946946416,93 -29502,1519947130719,87 -29503,1519947161068,83 -29504,1519947188579,84 -29505,1519947216477,86 -29506,1519947236746,89 -29507,1519947401405,92 -29508,1519947649601,88 -29509,1519947674194,93 -29510,1519947938187,95 -29511,1519947983208,89 -29512,1519948037063,88 -29513,1519948471865,86 -29514,1519948932085,81 -29515,1519949015042,76 -29516,1519949084710,71 -29517,1519949135788,73 -29518,1519949170892,70 -29519,1519949245917,70 -29520,1519949449949,68 -29521,1519949596495,63 -29522,1519949653701,58 -29523,1519949666310,54 -29524,1519949902055,60 -29525,1519949934721,55 -29526,1519949944708,64 -29527,1519950122196,73 -29528,1519950192649,68 -29529,1519950356030,74 -29530,1519950431324,77 -29531,1519950601894,74 -29532,1519950875681,69 -29533,1519951071289,64 -29534,1519951185258,59 -29535,1519951249995,55 -29536,1519951460944,75 -29537,1519951556730,70 -29538,1519951807767,67 -29539,1519951926917,65 -29540,1519951964088,62 -29541,1519952031003,61 -29542,1519952064853,60 -29543,1519952111538,59 -29544,1519952187405,59 -29545,1519952469917,56 -29546,1519952480009,60 -29547,1519952664995,70 -29548,1519952764798,67 -29549,1519952779739,64 -29550,1519952908361,79 -29551,1519953072935,77 -29552,1519953168289,82 -29553,1519953224234,80 -29554,1519953417599,78 -29555,1519953432718,76 -29556,1519953579707,83 -29557,1519953821077,83 -29558,1519953843638,79 -29559,1519953873065,87 -29560,1519953908501,89 -29561,1519953938709,90 -29562,1519953968238,93 -29563,1519954080406,99 -29564,1519954145062,98 -29565,1519954225894,97 -29566,1519954256056,96 -29567,1519954389596,101 -29568,1519954451649,98 -29569,1519954500834,98 -29570,1519954684914,98 -29571,1519954781563,94 -29572,1519954878453,92 -29573,1519954900712,91 -29574,1519955137921,102 -29575,1519955274484,100 -29576,1519955548607,97 -29577,1519955780022,94 -29578,1519955844524,91 -29579,1519955916275,90 -29580,1519955987819,88 -29581,1519956133766,85 -29582,1519956353578,84 -29583,1519956661177,81 -29584,1519956792223,76 -29585,1519956940919,74 -29586,1519957027319,70 -29587,1519957086699,70 -29588,1519957207772,68 -29589,1519957240616,65 -29590,1519957447213,65 -29591,1519957572791,62 -29592,1519957590046,62 -29593,1519957640288,68 -29594,1519957711380,67 -29595,1519957918280,68 -29596,1519958005702,64 -29597,1519958018177,62 -29598,1519958025853,70 -29599,1519958080217,87 -29600,1519958090276,98 -29601,1519958185494,117 -29602,1519958280350,114 -29603,1519958309806,112 -29604,1519958359607,119 -29605,1519958428384,123 -29606,1519958475358,124 -29607,1519958734160,131 -29608,1519958766454,127 -29609,1519958882554,131 -29610,1519959068153,133 -29611,1519959684162,129 -29612,1519959716350,126 -29613,1519959768725,132 -29614,1519959821311,132 -29615,1519959918299,134 -29616,1519960211562,131 -29617,1519960396748,128 -29618,1519960414092,126 -29619,1519960604888,140 -29620,1519960699410,136 -29621,1519960877152,134 -29622,1519961242035,131 -29623,1519961346408,126 -29624,1519961575438,129 -29625,1519961716097,125 -29626,1519961768321,122 -29627,1519961788044,130 -29628,1519962238618,141 -29629,1519962468802,137 -29630,1519962711666,133 -29631,1519962800417,129 -29632,1519963212822,127 -29633,1519963548090,123 -29634,1519963992678,118 -29635,1519964044644,113 -29636,1519964067311,113 -29637,1519964099768,119 -29638,1519964917152,123 -29639,1519965005669,117 -29640,1519965201036,114 -29641,1519965385415,112 -29642,1519965450167,108 -29643,1519965613964,108 -29644,1519965668474,105 -29645,1519965718732,104 -29646,1519965924338,103 -29647,1519965971830,105 -29648,1519965994352,105 -29649,1519966024400,110 -29650,1519966108215,118 -29651,1519966213329,115 -29652,1519966237926,112 -29653,1519966525888,118 -29654,1519966870937,114 -29655,1519966962310,108 -29656,1519966977300,112 -29657,1519967204375,123 -29658,1519967681320,118 -29659,1519967698997,117 -29660,1519968082604,130 -29661,1519968475188,127 -29662,1519968699197,125 -29663,1519969279919,124 -29664,1519969591133,119 -29665,1519969613696,115 -29666,1519969890050,123 -29667,1519969902467,121 -29668,1519969939544,139 -29669,1519970068376,143 -29670,1519970539121,142 -29671,1519971065397,136 -29672,1519971090868,132 -29673,1519971418899,138 -29674,1519971473321,137 -29675,1519971610156,137 -29676,1519971647304,133 -29677,1519971672550,136 -29678,1519971854462,143 -29679,1519972143472,139 -29680,1519972397117,134 -29681,1519972417121,130 -29682,1519972758327,139 -29683,1519973057616,133 -29684,1519973137345,127 -29685,1519973369419,124 -29686,1519973475742,120 -29687,1519973498315,116 -29688,1519973537359,123 -29689,1519973722996,123 -29690,1519973804982,119 -29691,1519973899720,116 -29692,1519974001044,112 -29693,1519974127706,111 -29694,1519974214070,108 -29695,1519974445304,104 -29696,1519974607184,99 -29697,1519975003202,94 -29698,1519975156950,92 -29699,1519975251881,98 -29700,1519975334045,95 -29701,1519975356669,103 -29702,1519975518471,109 -29703,1519975578506,105 -29704,1519975722113,107 -29705,1519975809766,106 -29706,1519976000490,104 -29707,1519976057764,101 -29708,1519976085172,100 -29709,1519976271692,107 -29710,1519976567974,103 -29711,1519976661980,98 -29712,1519976832343,94 -29713,1519976893827,94 -29714,1519977035546,95 -29715,1519977099925,92 -29716,1519977214556,91 -29717,1519977236877,87 -29718,1519977476685,91 -29719,1519977627457,95 -29720,1519977661483,91 -29721,1519977841382,93 -29722,1519978100867,89 -29723,1519978175096,84 -29724,1519978316388,82 -29725,1519978401586,78 -29726,1519978507040,74 -29727,1519978519822,73 -29728,1519978546750,89 -29729,1519978710539,91 -29730,1519978755106,87 -29731,1519978784598,85 -29732,1519978806967,88 -29733,1519979043873,92 -29734,1519979219625,86 -29735,1519979487926,82 -29736,1519979510916,79 -29737,1519979543255,86 -29738,1519979558279,91 -29739,1519979729491,99 -29740,1519979781549,95 -29741,1519979826640,94 -29742,1519979853904,94 -29743,1519979962243,97 -29744,1519980066191,93 -29745,1519980093366,91 -29746,1519980162335,95 -29747,1519980236494,92 -29748,1519980293682,91 -29749,1519980328814,94 -29750,1519980341238,98 -29751,1519980368531,112 -29752,1519980425461,117 -29753,1519980805393,121 -29754,1519980815553,115 -29755,1519980915263,135 -29756,1519980987431,133 -29757,1519981290772,139 -29758,1519981424855,134 -29759,1519981489094,130 -29760,1519981599518,136 -29761,1519981723579,132 -29762,1519981751238,128 -29763,1519981786338,134 -29764,1519981971243,136 -29765,1519982013358,131 -29766,1519982228545,137 -29767,1519982263816,132 -29768,1519982656454,146 -29769,1519982752921,144 -29770,1519982790501,143 -29771,1519982948865,145 -29772,1519983040252,141 -29773,1519983217191,144 -29774,1519983232116,139 -29775,1519983398250,158 -29776,1519983706114,154 -29777,1519983811169,153 -29778,1519984128735,156 -29779,1519984267549,151 -29780,1519984481473,148 -29781,1519984584290,143 -29782,1519984768528,148 -29783,1519985088877,144 -29784,1519985166988,138 -29785,1519985357740,138 -29786,1519985394522,134 -29787,1519985607680,137 -29788,1519985732226,138 -29789,1519985802109,137 -29790,1519985930839,136 -29791,1519986013008,134 -29792,1519986141010,134 -29793,1519986261010,130 -29794,1519986344495,127 -29795,1519986361886,126 -29796,1519986574709,137 -29797,1519986703509,133 -29798,1519986951929,129 -29799,1519986987003,123 -29800,1519987068458,126 -29801,1519987078215,124 -29802,1519987095510,154 -29803,1519987317089,168 -29804,1519987337109,165 -29805,1519987518884,178 -29806,1519987703645,173 -29807,1519988060998,169 -29808,1519988333512,165 -29809,1519988470135,163 -29810,1519988559365,158 -29811,1519988626700,155 -29812,1519988685880,155 -29813,1519988766212,154 -29814,1519988938839,152 -29815,1519989018737,148 -29816,1519989525727,146 -29817,1519989576311,139 -29818,1519989732509,143 -29819,1519989773831,137 -29820,1519989837408,139 -29821,1519989961402,138 -29822,1519989992760,134 -29823,1519990013205,137 -29824,1519990224609,146 -29825,1519990288288,140 -29826,1519990606425,137 -29827,1519990771107,132 -29828,1519991043753,132 -29829,1519991353253,130 -29830,1519991607895,123 -29831,1519991906133,118 -29832,1519992041328,114 -29833,1519992054145,114 -29834,1519992106953,128 -29835,1519992205037,126 -29836,1519992531529,121 -29837,1519992860982,118 -29838,1519992957194,114 -29839,1519993138349,116 -29840,1519993196954,111 -29841,1519993288222,110 -29842,1519993507200,107 -29843,1519993963007,105 -29844,1519994121869,99 -29845,1519994472838,94 -29846,1519994505593,90 -29847,1519994558791,92 -29848,1519994596834,90 -29849,1519994624703,89 -29850,1519994637262,92 -29851,1519994704145,112 -29852,1519994949223,114 -29853,1519995165617,110 -29854,1519995180921,104 -29855,1519995498598,127 -29856,1519995582262,121 -29857,1519995707099,120 -29858,1519995880931,116 -29859,1519995969219,110 -29860,1519996134849,109 -29861,1519996523069,105 -29862,1519996680441,100 -29863,1519996723402,99 -29864,1519996738746,103 -29865,1519997092792,112 -29866,1519997401570,110 -29867,1519997447268,104 -29868,1519997689000,108 -29869,1519997995457,102 -29870,1519998013307,97 -29871,1519998038610,108 -29872,1519998069110,112 -29873,1519998182559,115 -29874,1519998255909,111 -29875,1519998389066,119 -29876,1519998928568,116 -29877,1519998976758,110 -29878,1519999256493,110 -29879,1519999271914,104 -29880,1519999407112,115 -29881,1519999449665,110 -29882,1519999658515,111 -29883,1520000102604,106 -29884,1520000185693,99 -29885,1520000272372,98 -29886,1520000305222,94 -29887,1520000358198,98 -29888,1520000541455,96 -29889,1520000563991,91 -29890,1520000771117,96 -29891,1520001883828,91 -29892,1520001908836,86 -29893,1520001949626,87 -29894,1520001964904,87 -29895,1520002080434,95 -29896,1520002246471,98 -29897,1520002532855,93 -29898,1520002684040,88 -29899,1520002731850,83 -29900,1520002895179,83 -29901,1520002941264,79 -29902,1520003004269,92 -29903,1520003024399,100 -29904,1520003406110,106 -29905,1520003443988,111 -29906,1520003938314,112 -29907,1520004001761,107 -29908,1520004042316,105 -29909,1520004126527,106 -29910,1520004134211,104 -29911,1520004159566,132 -29912,1520004368434,140 -29913,1520004414727,138 -29914,1520004572692,141 -29915,1520004702447,137 -29916,1520005020520,134 -29917,1520005075778,129 -29918,1520005096371,130 -29919,1520005305664,140 -29920,1520005321006,139 -29921,1520005586106,156 -29922,1520005593722,151 -29923,1520006128405,197 -29924,1520006680747,198 -29925,1520006779908,192 -29926,1520006835569,191 -29927,1520007129118,193 -29928,1520007397787,188 -29929,1520007430805,182 -29930,1520007643435,188 -29931,1520008155865,183 -29932,1520008472528,176 -29933,1520008497953,170 -29934,1520008714856,190 -29935,1520008818341,186 -29936,1520009472444,185 -29937,1520010028254,178 -29938,1520010086344,171 -29939,1520010306315,172 -29940,1520010510695,167 -29941,1520010684576,163 -29942,1520010779052,159 -29943,1520010850427,156 -29944,1520010935281,153 -29945,1520011061411,150 -29946,1520011223876,146 -29947,1520011267169,143 -29948,1520011350435,145 -29949,1520011509016,144 -29950,1520011724073,143 -29951,1520011841417,145 -29952,1520011963823,142 -29953,1520012219393,138 -29954,1520012287530,132 -29955,1520012397067,138 -29956,1520012477874,133 -29957,1520012761085,131 -29958,1520012922742,126 -29959,1520013210019,121 -29960,1520013354163,116 -29961,1520013387931,111 -29962,1520013607596,112 -29963,1520013685676,107 -29964,1520013781272,105 -29965,1520013832603,108 -29966,1520014059489,106 -29967,1520014235590,100 -29968,1520014582220,97 -29969,1520014645982,91 -29970,1520014685923,87 -29971,1520014762216,92 -29972,1520014779829,92 -29973,1520014938092,103 -29974,1520015150516,98 -29975,1520015467097,93 -29976,1520015823925,88 -29977,1520015830415,82 -29978,1520015838316,108 -29979,1520015937355,134 -29980,1520016168145,137 -29981,1520016353808,131 -29982,1520016663357,129 -29983,1520016789371,122 -29984,1520016955011,117 -29985,1520016993123,112 -29986,1520017028490,113 -29987,1520017061056,116 -29988,1520017145136,119 -29989,1520017268128,116 -29990,1520017578448,115 -29991,1520017588708,108 -29992,1520017631542,126 -29993,1520017639188,129 -29994,1520017685131,164 -29995,1520017791234,171 -29996,1520017952393,167 -29997,1520017980225,161 -29998,1520018103762,167 -29999,1520018189807,162 -30000,1520018492828,160 -30001,1520018555662,153 -30002,1520018986329,152 -30003,1520019289025,146 -30004,1520019401889,144 -30005,1520019466840,138 -30006,1520019626359,138 -30007,1520019634154,132 -30008,1520019651928,166 -30009,1520019781828,182 -30010,1520020273417,177 -30011,1520020438875,185 -30012,1520020675314,185 -30013,1520020833366,179 -30014,1520021410391,177 -30015,1520021549817,170 -30016,1520021744857,165 -30017,1520022151888,159 -30018,1520022277746,153 -30019,1520022358614,155 -30020,1520022373864,152 -30021,1520022472122,179 -30022,1520022540158,175 -30023,1520022772667,196 -30024,1520023256438,191 -30025,1520023541788,184 -30026,1520023819451,180 -30027,1520024539006,177 -30028,1520024662746,170 -30029,1520024716162,167 -30030,1520024774045,173 -30031,1520025015929,174 -30032,1520025056793,167 -30033,1520025364366,170 -30034,1520025409944,171 -30035,1520025671484,173 -30036,1520025770484,169 -30037,1520025920941,165 -30038,1520026020057,161 -30039,1520026116516,161 -30040,1520026212891,157 -30041,1520026253627,154 -30042,1520026293548,156 -30043,1520026472690,159 -30044,1520026496068,156 -30045,1520026647632,166 -30046,1520026693269,161 -30047,1520026992944,163 -30048,1520027190186,159 -30049,1520027223218,155 -30050,1520027289500,159 -30051,1520027395004,157 -30052,1520027460678,154 -30053,1520027651665,152 -30054,1520027702009,146 -30055,1520027760235,147 -30056,1520027816595,146 -30057,1520027991384,145 -30058,1520028179297,139 -30059,1520028302808,133 -30060,1520028435526,127 -30061,1520028707189,122 -30062,1520028723863,118 -30063,1520028741517,127 -30064,1520028822607,137 -30065,1520028858156,133 -30066,1520028918377,136 -30067,1520029195534,132 -30068,1520029223422,125 -30069,1520029342875,127 -30070,1520029373287,122 -30071,1520029408747,124 -30072,1520029595210,125 -30073,1520029662744,124 -30074,1520029801306,119 -30075,1520029849358,112 -30076,1520029897937,108 -30077,1520030059844,105 -30078,1520030109752,112 -30079,1520030184540,126 -30080,1520030224837,122 -30081,1520030327954,122 -30082,1520030374183,117 -30083,1520030500466,114 -30084,1520030752438,108 -30085,1520030762327,102 -30086,1520030904012,121 -30087,1520030968870,118 -30088,1520031251708,118 -30089,1520031339500,111 -30090,1520031390336,107 -30091,1520031436394,103 -30092,1520031664926,112 -30093,1520031680396,109 -30094,1520031695999,137 -30095,1520031998329,155 -30096,1520032081720,149 -30097,1520032089304,146 -30098,1520032249517,191 -30099,1520032310295,187 -30100,1520032330251,187 -30101,1520032428505,201 -30102,1520032649580,199 -30103,1520032724964,193 -30104,1520033048882,190 -30105,1520033081436,183 -30106,1520033157920,190 -30107,1520033188194,187 -30108,1520033253703,214 -30109,1520033464296,224 -30110,1520033469025,219 -30111,1520033882789,322 -30112,1520034587856,315 -30113,1520034725794,306 -30114,1520035657803,302 -30115,1520035787626,293 -30116,1520035902272,288 -30117,1520036345368,285 -30118,1520036521888,276 -30119,1520036537599,271 -30120,1520036600368,303 -30121,1520036643656,316 -30122,1520036797617,325 -30123,1520037205988,322 -30124,1520037564091,314 -30125,1520037792878,305 -30126,1520037835924,297 -30127,1520037884040,303 -30128,1520038286608,306 -30129,1520038714329,299 -30130,1520038887633,292 -30131,1520039301695,288 -30132,1520039558344,279 -30133,1520039726178,275 -30134,1520039762157,268 -30135,1520039961306,279 -30136,1520040033030,272 -30137,1520040197437,271 -30138,1520041195454,264 -30139,1520041596118,255 -30140,1520041648432,247 -30141,1520042138977,248 -30142,1520042481320,242 -30143,1520042600954,237 -30144,1520042700435,231 -30145,1520042723346,234 -30146,1520042872386,248 -30147,1520042907711,245 -30148,1520043054067,249 -30149,1520043073515,243 -30150,1520043622606,267 -30151,1520044130297,258 -30152,1520044199133,249 -30153,1520044293640,248 -30154,1520044372182,243 -30155,1520044546697,241 -30156,1520045079871,236 -30157,1520045105101,228 -30158,1520045209269,239 -30159,1520045532284,233 -30160,1520046443568,223 -30161,1520046574070,212 -30162,1520046763490,204 -30163,1520047038832,203 -30164,1520047145385,200 -30165,1520047237676,195 -30166,1520047525058,193 -30167,1520047819067,185 -30168,1520047871907,175 -30169,1520048100363,176 -30170,1520048256309,167 -30171,1520048396798,163 -30172,1520048425078,159 -30173,1520048455470,161 -30174,1520048650397,163 -30175,1520048871938,154 -30176,1520049023305,146 -30177,1520049095550,140 -30178,1520049274936,133 -30179,1520049304113,126 -30180,1520049351135,127 -30181,1520049569252,124 -30182,1520049756014,115 -30183,1520049995945,107 -30184,1520050094135,97 -30185,1520050116837,88 -30186,1520050155054,99 -30187,1520050368359,94 -30188,1520050380995,86 -30189,1520050514389,91 -30190,1520050761176,82 -30191,1520050822420,73 -30192,1520050850286,67 -30193,1520050919351,61 -30194,1520050997159,60 -30195,1520051014898,62 -30196,1520051067766,59 -30197,1520051223833,53 -30198,1520051261919,65 -30199,1520051351025,60 -30200,1520051381349,55 -30201,1520051470245,60 -30202,1520051787823,54 -30203,1520051808033,45 -30204,1520051889857,43 -30205,1520051900113,34 -30206,1520051925398,39 -30207,1520051960693,35 \ No newline at end of file diff --git a/ergo-core/src/test/resources/execute-script.json b/ergo-core/src/test/resources/execute-script.json deleted file mode 100644 index 104b871c9e..0000000000 --- a/ergo-core/src/test/resources/execute-script.json +++ /dev/null @@ -1,1185 +0,0 @@ -{ - "script": "{ (HEIGHT > deadline) }", - "namedConstants": {"deadline": {"type": "Int", "value": 1}, - "pkA": { "type": "String", "value": "12345678" } }, - "context": { - "scriptVersion": 1, - "lastBlockUtxoRoot" : { - "digest" : "000000000000000000000000000000000000000000000000000000000000000000", - "treeFlags" : 7, - "keyLength" : 32, - "valueLength" : null - }, - "headers" : [ - ], - "preHeader" : { - "votes" : "", - "timestamp" : 3, - "height" : 10, - "nBits" : 0, - "version" : 0, - "minerPk" : "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "parentId" : "" - }, - "dataBoxes" : [ - ], - "boxesToSpend" : [ - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - }, - { - "boxId" : "68a04e9532e9cb721e0a8f74e60e73fe9357eba62095acd98e1154d1440b99d2", - "value" : 1, - "ergoTree" : "10010101d17300", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "0000000000000000000000000000000000000000000000000000000000000000", - "index" : 0 - } - ], - "spendingTransaction" : { - "id" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "inputs" : [ - ], - "dataInputs" : [ - ], - "outputs" : [ - { - "boxId" : "0bf4750cc49f27e5e9a9b370728ba2186313551e4a6287fdbce6d61a65e051f8", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 0 - }, - { - "boxId" : "28030edabb0ebc394313d662069ac216ad300de866888644b89f323e8bcd8d61", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 1 - }, - { - "boxId" : "371bfda55caa125253f178d0b08be672d1c6ae5a372055b979708d8430b0cbd8", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 2 - }, - { - "boxId" : "a307d01a482b05d5311f60462237fd83d6d7aedeb918baeaca6713f0089e67fc", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 3 - }, - { - "boxId" : "a40369be6d85d6c400e92d1ab209ad856dd10ae92bad99cb9b2e1370e86323d3", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 4 - }, - { - "boxId" : "883e8d2639532e23cb4970b4fb95575d7da3b9e683f1abd6db473b25c3c9a4c5", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 5 - }, - { - "boxId" : "6e50542c7efee569e021b07939c13d79bfedb213842abaaf22a28f696595df80", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 6 - }, - { - "boxId" : "3957e356e47b26133d71fd8849bfc1ee3df9a02319e90f0d0585f83cfc734eb5", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 7 - }, - { - "boxId" : "66198e6ac8b0b522bbe8434cdce8641e5cdedf0741898ba0104f9ed7c82b6285", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 8 - }, - { - "boxId" : "04f8f69d0b719f6dd0a6872f53b58da55ca9644de467a047182999616f3deb13", - "value" : 1, - "ergoTree" : "0008cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "assets" : [ - { - "tokenId" : "8028007f7fb72f005b01eb000064ff004e0080e58b68ffb700007f8417360000", - "amount" : 2 - }, - { - "tokenId" : "1dee7f8701080a5a4e457f95ffe39e00eaea006a4c01018089607f83800001e8", - "amount" : 2 - }, - { - "tokenId" : "011b010900017f017f8001005d01f97fffa71700c400ff887f80f0a7b37f0080", - "amount" : 2 - }, - { - "tokenId" : "c7e300a94ca200e940ff7fb18eff28747f00dacfb87f5d007f7f8080440011fb", - "amount" : 2 - }, - { - "tokenId" : "cc7f56fff1fa7f017fff859b012effb080068056cb80e1017596b3cab14f6e59", - "amount" : 2 - }, - { - "tokenId" : "23c1801e2392018004f6807f00ca807fff3e01fc00d8e20100f6805f5a7facff", - "amount" : 2 - }, - { - "tokenId" : "d2ff907f1f807f0100b27f807f12bb7f00ff824e53c37380ff80ffc3fb010501", - "amount" : 2 - }, - { - "tokenId" : "ee7f3dec00008080fd00e56fae80748cd7ff36acf401803b00657ff57e2e0158", - "amount" : 2 - }, - { - "tokenId" : "7ff4019a0180017f7f8ba8808cff46664100d2807f30800165008438dc807f68", - "amount" : 2 - }, - { - "tokenId" : "53017c7c7001007f9a2cffdc7f011180ff7f6a010a7fff00ff27007f00ff80ff", - "amount" : 2 - } - ], - "creationHeight" : 10, - "additionalRegisters" : { - "R4" : "0201", - "R5" : "08cd02a73151bd3c8864d6cf9c81fa288df7940ea828dd6ccf96c8437805076c851fa0", - "R6" : "0414", - "R7" : "0e0a0a0a0a0a0a0a0a0a0a0a", - "R8" : "0ece1f0202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202" - }, - "transactionId" : "a9facd3e2a7c6a9253bbb6cfc5a535762d30f3459bedef04a46b8ea8de5e4ccb", - "index" : 9 - } - ] - }, - "selfIndex" : 0, - "extension" : { - - }, - "validationSettings" : "10e8070001e9070001ea070001eb070001ec070001ed070001ee070001ef070001f0070001f1070001f2070001f3070001f4070001f5070001f6070001f7070001", - "costLimit" : 1000000, - "initCost" : 0 - } -} \ No newline at end of file diff --git a/ergo-core/src/test/resources/logback-test.xml b/ergo-core/src/test/resources/logback-test.xml deleted file mode 100644 index f3a04e2b7b..0000000000 --- a/ergo-core/src/test/resources/logback-test.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - System.out - - WARN - - - [%thread] >> [%-5level] %logger{36} >> %d{HH:mm:ss.SSS} %msg%n - - - - - - - - diff --git a/ergo-core/src/test/resources/settings.conf b/ergo-core/src/test/resources/settings.conf deleted file mode 100644 index ad5b2ff500..0000000000 --- a/ergo-core/src/test/resources/settings.conf +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ergo": { - "node": { - "blocksToKeep": 13, - "mempoolSorting": "bySize" - } - } -} \ No newline at end of file diff --git a/ergo-core/src/test/resources/settings.json b/ergo-core/src/test/resources/settings.json deleted file mode 100644 index f9d813aa9a..0000000000 --- a/ergo-core/src/test/resources/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ergo": { - "node": { - "blocksToKeep": 12, - "mempoolSorting": "bySize" - } - } -} \ No newline at end of file diff --git a/ergo-core/src/test/scala/org/ergoplatform/db/DBSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/db/DBSpec.scala deleted file mode 100644 index f2617ee32a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/db/DBSpec.scala +++ /dev/null @@ -1,43 +0,0 @@ -package org.ergoplatform.db - -import akka.util.ByteString -import org.ergoplatform.settings.Algos -import org.ergoplatform.wallet.utils.TestFileUtils -import org.iq80.leveldb.{DB, Options} -import scorex.db.LDBFactory.factory -import scorex.db.{LDBKVStore, LDBVersionedStore} - -trait DBSpec extends TestFileUtils { - - implicit class ValueOps(x: Option[Array[Byte]]) { - def toBs: Option[ByteString] = x.map(ByteString.apply) - } - - implicit class KeyValueOps(xs: Seq[(Array[Byte], Array[Byte])]) { - def toBs: Seq[(ByteString, ByteString)] = xs.map(x => ByteString(x._1) -> ByteString(x._2)) - } - - protected def byteString(s: String): Array[Byte] = s.getBytes("UTF-8") - - protected def byteString32(s: String): Array[Byte] = Algos.hash(byteString(s)) - - protected def withDb(body: DB => Unit): Unit = { - val options = new Options() - options.createIfMissing(true) - options.verifyChecksums(true) - options.maxOpenFiles(2000) - val db = factory.open(createTempDir, options) - try body(db) finally db.close() - } - - protected def versionId(s: String): Array[Byte] = byteString32(s) - - protected def withStore(body: LDBKVStore => Unit): Unit = - withDb { db: DB => body(new LDBKVStore(db)) } - - protected def withVersionedStore(keepVersions: Int)(body: LDBVersionedStore => Unit): Unit = { - val db = new LDBVersionedStore(createTempDir, keepVersions) - try body(db) finally db.close() - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/db/KvStoreReaderSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/db/KvStoreReaderSpec.scala deleted file mode 100644 index 9159876876..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/db/KvStoreReaderSpec.scala +++ /dev/null @@ -1,35 +0,0 @@ -package org.ergoplatform.db - -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec - -class KvStoreReaderSpec extends AnyPropSpec with Matchers with DBSpec { - - property("getRange works properly") { - withStore {store => - val keyStart = byteString("A") - val keyEnd = byteString("Z") - store.getRange(keyStart, keyEnd).length shouldBe 0 - - store.insert(keyStart, keyStart).get - store.getRange(keyStart, keyEnd).length shouldBe 1 - - store.insert(keyEnd, keyEnd).get - store.getRange(keyStart, keyEnd).length shouldBe 2 - - // keys before the range - store.getRange(byteString("a"), byteString("z")).length shouldBe 0 - - // keys inside the range - store.getRange(byteString("<"), byteString("z")).length shouldBe 2 - - // keys after the range - store.getRange(byteString("<"), byteString("?")).length shouldBe 0 - - //removing keys - store.remove(Array(keyStart, keyEnd)).get - store.getRange(keyStart, keyEnd).length shouldBe 0 - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/db/LDBKVStoreSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/db/LDBKVStoreSpec.scala deleted file mode 100644 index cd32b21c29..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/db/LDBKVStoreSpec.scala +++ /dev/null @@ -1,64 +0,0 @@ -package org.ergoplatform.db - -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec - -class LDBKVStoreSpec extends AnyPropSpec with Matchers with DBSpec { - - property("put/get/getAll/delete") { - withStore { store => - val valueA = (byteString("A"), byteString("1")) - val valueB = (byteString("B"), byteString("2")) - - store.update(Array(valueA._1, valueB._1), Array(valueA._2, valueB._2), toRemove = Array.empty).get - - store.get(valueA._1).toBs shouldBe Some(valueA._2).toBs - store.get(valueB._1).toBs shouldBe Some(valueB._2).toBs - - store.getAll.toSeq.toBs shouldBe Seq(valueA, valueB).toBs - - store.update(Array.empty, Array.empty, toRemove = Array(valueA._1)).get - store.get(valueA._1) shouldBe None - } - } - - property("record rewriting") { - withStore { store => - val key = byteString("A") - val valA = byteString("1") - val valB = byteString("2") - - store.insert(key, valA).get - - store.get(key).toBs shouldBe Some(valA).toBs - - store.insert(key, valB).get - - store.get(key).toBs shouldBe Some(valB).toBs - - store.getAll.size shouldBe 1 - } - } - - property("last key in range") { - withStore { store => - val valueA = (byteString("A"), byteString("1")) - val valueB = (byteString("B"), byteString("2")) - val valueC = (byteString("C"), byteString("1")) - val valueD = (byteString("D"), byteString("2")) - val valueE = (byteString("E"), byteString("3")) - val valueF = (byteString("F"), byteString("4")) - - val values = Array(valueA, valueB, valueC, valueD, valueE, valueF) - store.insert(values.map(_._1), values.map(_._2)).get - - store.lastKeyInRange(valueA._1, valueC._1).get.toSeq shouldBe valueC._1.toSeq - store.lastKeyInRange(valueD._1, valueF._1).get.toSeq shouldBe valueF._1.toSeq - store.lastKeyInRange(valueF._1, byteString32("Z")).get.toSeq shouldBe valueF._1.toSeq - store.lastKeyInRange(Array(10: Byte), valueA._1).get.toSeq shouldBe valueA._1.toSeq - - store.lastKeyInRange(Array(10: Byte), Array(11: Byte)).isDefined shouldBe false - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/db/VersionedStoreSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/db/VersionedStoreSpec.scala deleted file mode 100644 index 59aa72d8b0..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/db/VersionedStoreSpec.scala +++ /dev/null @@ -1,87 +0,0 @@ -package org.ergoplatform.db - -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec - -class VersionedStoreSpec extends AnyPropSpec with Matchers with DBSpec { - - private val (keyA, valA) = (byteString("A"), byteString("1")) - private val (keyB, valB) = (byteString("B"), byteString("2")) - private val (keyC, valC) = (byteString("C"), byteString("3")) - private val (keyD, valD) = (byteString("D"), byteString("4")) - private val (keyE, valE) = (byteString("E"), byteString("5")) - - private val v1 = versionId("v1") - private val v2 = versionId("v2") - private val v3 = versionId("v3") - private val v4 = versionId("v4") - - property("rollback (1 version back)") { - withVersionedStore(10) { store => - store.insert(v1, Seq(keyA -> valA)).get - store.insert(v2, Seq(keyB -> valB, keyC -> valC)).get - store.update(v3, Seq(keyC), Seq(keyA -> byteString("6"), keyD -> valD)).get - - store.getAll.toSeq.toBs should contain allElementsOf Seq( - keyA -> byteString("6"), - keyB -> valB, - keyD -> valD - ).toBs - - store.rollbackTo(v2) shouldBe 'success - - store.getAll.toSeq.toBs should contain allElementsOf Seq(keyA -> valA, keyB -> valB, keyC -> valC).toBs - store.get(keyD) shouldBe None - store.get(keyA).get.sameElements(valA) shouldBe true - - store.lastVersionID shouldBe Some(v2) - } - } - - property("rollback (2 versions back)") { - withVersionedStore(10) { store => - store.insert(v1, Seq(keyA -> valA)).get - store.insert(v2, Seq(keyB -> valB, keyC -> valC)).get - store.update(v3, Seq(keyC), Seq(keyA -> byteString("6"), keyD -> valD)).get - store.update(v4, Seq(keyA), Seq(keyB -> byteString("7"), keyE -> valE)).get - - store.getAll.toSeq.toBs should contain allElementsOf Seq(keyB -> byteString("7"), keyE -> valE, keyD -> valD).toBs - store.get(keyC) shouldBe None - store.get(keyA) shouldBe None - - store.rollbackTo(v2) shouldBe 'success - - store.getAll.toSeq.toBs should contain allElementsOf Seq(keyA -> valA, keyB -> valB, keyC -> valC).toBs - store.get(keyE) shouldBe None - store.get(keyD) shouldBe None - } - } - - property("Outdated versions pruning") { - withVersionedStore(2) { store => - store.insert(v1, Seq(keyA -> valA)).get - store.insert(v2, Seq(keyB -> valB)).get - - store.versionIdExists(v1) shouldBe true - - store.insert(v3, Seq(keyC -> valC)).get - store.insert(v4, Seq(keyA -> valA)).get - - store.versionIdExists(v4) shouldBe true - store.versionIdExists(v3) shouldBe true - store.versionIdExists(v2) shouldBe true - store.versionIdExists(v1) shouldBe false - - store.get(keyA).isDefined shouldBe true - store.get(keyB).isDefined shouldBe true - store.get(keyC).isDefined shouldBe true - - store.rollbackTo(v1).isSuccess shouldBe false - - store.get(keyA).isDefined shouldBe true - store.get(keyB).isDefined shouldBe true - store.get(keyC).isDefined shouldBe true - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/examples/LiteClientExamples.scala b/ergo-core/src/test/scala/org/ergoplatform/examples/LiteClientExamples.scala deleted file mode 100644 index d90cf00afc..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/examples/LiteClientExamples.scala +++ /dev/null @@ -1,106 +0,0 @@ -package org.ergoplatform.examples - -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.crypto.authds.merkle.MerkleProof -import scorex.crypto.authds.{LeafData, Side} -import scorex.crypto.hash.{Blake2b256, Digest32} -import scorex.util.encode.Base16 - -/** - * This class contains how-to examples for building clients - */ -class LiteClientExamples extends ErgoPropertyTest { - - /** - * This code shows how to do a client checking a Merkle-tree based membership proof against an - * incomplete header (so header without a proof-of-work solution). This could be useful for a - * decentralized pool with collaterals, where the pool checks shares from miners, and a share - * includes proof that a corresponding block contains a certain transaction (paying to the pool). - * - * For example, a working scheme for a decentralized pool could be as follows: - * 1. A miner is creating a transaction which is paying to the pool - * (posting of the tx by the pool outside the block should be impossible) - * 2. The miner is creating block candidate with the tx included (via calling "mining/candidateWithTxs"). - * The result would be like the following: - * { - * "msg" : "6cb37d0a202bc2984f43de003cbc5558804db45798d0fc8faae7390b96d42d15", - * "b" : 748014723576678314041035877227113663879264849498014394977645987, - * "pk" : "0278011ec0cf5feb92d61adb51dcb75876627ace6fd9446ab4cabc5313ab7b39a7", - * "proof" : { - * "msgPreimage" : "01fb9e35f8a73c128b73e8fde5c108228060d68f11a69359ee0fb9bfd84e7ecde6d19957ccbbe75b075b3baf1cac6126b6e80b5770258f4cec29fbde92337faeec74c851610658a40f5ae74aa3a4babd5751bd827a6ccc1fe069468ef487cb90a8c452f6f90ab0b6c818f19b5d17befd85de199d533893a359eb25e7804c8b5d7514d784c8e0e52dabae6e89a9d6ed9c84388b228e7cdee09462488c636a87931d656eb8b40f82a507008ccacbee05000000", - * "txProofs" : [{ - * "leaf" : "642c15c62553edd8fd9af9a6f754f3c7a6c03faacd0c9b9d5b7d11052c6c6fe8", - * "levels" : [ - * "0139b79af823a92aa72ced2c6d9e7f7f4687de5b5af7fab0ad205d3e54bda3f3ae" - * ] - * }] - * } - * } - * 3. The miner is mining the block using "msg", "b", "pk" as it happens now. If block is found, the miner is - * posting the transaction to the network. However, if real difficulty of the solution is not enough to form a - * block but enough for a share, then the miner can post the share to the pool. The share consists of "msg", "b", - * "pk", solution and the "proof". - * - * 4. The pool checks that the share is valid. In particular, the pool checks that: - * a) the "msgPreimage" (which is a header without a PoW solution) along with the PoW form a valid header - * with enough difficulty - * b) the header contains transaction by using "proof" - * - * The code below is about step 4b only. - */ - property("Example client code for tx proof") { - implicit val hashFn: Blake2b256.type = Blake2b256 - - val msgPreimageBase16 = "01fb9e35f8a73c128b73e8fde5c108228060d68f11a69359ee0fb9bfd84e7ecde6d19957ccbbe75b075b3baf1cac6126b6e80b5770258f4cec29fbde92337faeec74c851610658a40f5ae74aa3a4babd5751bd827a6ccc1fe069468ef487cb90a8c452f6f90ab0b6c818f19b5d17befd85de199d533893a359eb25e7804c8b5d7514d784c8e0e52dabae6e89a9d6ed9c84388b228e7cdee09462488c636a87931d656eb8b40f82a507008ccacbee05000000" - val msgPreimage = Base16.decode(msgPreimageBase16).get - - val msg = "6cb37d0a202bc2984f43de003cbc5558804db45798d0fc8faae7390b96d42d15" - - //hash of "msgPreimage" (which is a header without PoW) should be equal to "msg" - Base16.encode(hashFn(msgPreimage)) == msg - - //Transactions Merkle tree digest is in bytes 65-96 (inclusive) of the unproven header - val txsRoot = msgPreimage.slice(65, 97) - - //txId is a "leaf" in a Merkle proof - val txId = "642c15c62553edd8fd9af9a6f754f3c7a6c03faacd0c9b9d5b7d11052c6c6fe8" - - // Merkle roof is constructed by given leaf data, leaf hash sibling and also siblings for parent nodes. Using this - // data, it is possible to compute nodes on the path to root hash, and the hash itself. The picture of a proof - // given below. In the picture, "^^" is leaf data(to compute leaf hash from), "=" values are to be computed, - // "*" values are to be stored. - // - // ........= Root - // ..... / \ - // .... * = - // ....... / \ - // ...... * = - // ......... /.\ - // .........* = - // ............ ^^ - // - // Merkle proof element is encoded in the following way: - // - first, 1 byte showing whether COMPUTED value is on the right (1) or on the left (0) - // - second, 32 bytes of stored value - - // To check the proof, first, hash of the leaf should be computed with the 1-byte zero prefix - // (i.e. blake2b256(0 ++ leaf). Then, for each level, if the first byte is "right" (1) then - // computed hash for the next level is blake2b256(1 ++ COMPUTED ++ stored hash (last 32 bytes of the level), - // where COMPUTED is the value computed on the previous step (and "1" is internal node prefix). - // A value computed on the last step is to be compared with expected root hash value. - - val levelsEncoded = Seq("0139b79af823a92aa72ced2c6d9e7f7f4687de5b5af7fab0ad205d3e54bda3f3ae") - - val levels = levelsEncoded.map { le => - val leBytes = Base16.decode(le).get - val side: Byte = leBytes.head - val digest = leBytes.tail - (Digest32 @@ digest, Side @@ side) - } - - val merkleProof = MerkleProof[Digest32](LeafData @@ Base16.decode(txId).get, levels) - - merkleProof.valid(Digest32 @@ txsRoot) shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/BlocksApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/BlocksApiRouteSpec.scala deleted file mode 100644 index 7edef059f5..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/BlocksApiRouteSpec.scala +++ /dev/null @@ -1,137 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes, UniversalEntity} -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.http.api.BlocksApiRoute -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.Stubs -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.util.ModifierId - -class BlocksApiRouteSpec - extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport - with Stubs { - - val prefix = "/blocks" - - val route: Route = BlocksApiRoute(nodeViewRef, digestReadersRef, settings).route - - val headerIdBytes: ModifierId = history.lastHeaders(1).headers.head.id - val headerIdString: String = Algos.encode(headerIdBytes) - - it should "get last blocks" in { - Get(prefix) ~> route ~> check { - status shouldBe StatusCodes.OK - history - .headerIdsAt(0, 50) - .map(Algos.encode) - .asJson shouldEqual responseAs[Json] - } - } - - it should "post block correctly" in { - val (st, bh) = createUtxoState(settings) - val block: ErgoFullBlock = validFullBlock(parentOpt = None, st, bh) - val blockJson: UniversalEntity = - HttpEntity(block.asJson.toString).withContentType(ContentTypes.`application/json`) - Post(prefix, blockJson) ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "get last headers" in { - Get(prefix + "/lastHeaders/1") ~> route ~> check { - status shouldBe StatusCodes.OK - history - .lastHeaders(1) - .headers - .map(_.asJson) - .asJson shouldEqual responseAs[Json] - } - } - - it should "get block at height" in { - Get(prefix + "/at/0") ~> route ~> check { - status shouldBe StatusCodes.OK - history - .headerIdsAtHeight(0) - .map(Algos.encode) - .asJson shouldEqual responseAs[Json] - } - } - - it should "get chain slice" in { - Get(prefix + "/chainSlice?fromHeight=0") ~> route ~> check { - status shouldBe StatusCodes.OK - chain.map(_.header).asJson shouldEqual responseAs[Json] - } - Get(prefix + "/chainSlice?fromHeight=2&toHeight=4") ~> route ~> check { - status shouldBe StatusCodes.OK - chain.slice(2, 4).map(_.header).asJson shouldEqual responseAs[Json] - } - } - - it should "get block by header id" in { - Get(prefix + "/" + headerIdString) ~> route ~> check { - status shouldBe StatusCodes.OK - val expected = history - .typedModifierById[Header](headerIdBytes) - .flatMap(history.getFullBlock) - .map(_.asJson) - .get - - responseAs[Json] shouldEqual expected - } - } - - it should "get blocks by header ids" in { - val headerIdsBytes = history.lastHeaders(10).headers - val headerIdsString: Seq[String] = headerIdsBytes.map(h => Algos.encode(h.id)) - - Post(prefix + "/headerIds", headerIdsString.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - - val expected = headerIdsBytes - .map(_.id) - .flatMap(headerId => - history.typedModifierById[Header](headerId).flatMap(history.getFullBlock) - ) - - responseAs[Seq[ErgoFullBlock]] shouldEqual expected - } - } - - it should "get header by header id" in { - Get(prefix + "/" + headerIdString + "/header") ~> route ~> check { - status shouldBe StatusCodes.OK - val expected = history - .typedModifierById[Header](headerIdBytes) - .flatMap(history.getFullBlock) - .map(_.header.asJson) - .get - - responseAs[Json] shouldEqual expected - } - } - - it should "get transactions by header id" in { - Get(prefix + "/" + headerIdString + "/transactions") ~> route ~> check { - status shouldBe StatusCodes.OK - val header = history.typedModifierById[Header](headerIdBytes).value - val fullBlock = history.getFullBlock(header).value - val expected = fullBlock.blockTransactions.asJson - responseAs[Json] shouldEqual expected - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala deleted file mode 100644 index 7d89b239a5..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala +++ /dev/null @@ -1,51 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} -import akka.testkit.TestDuration -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.http.api.EmissionApiRoute -import org.ergoplatform.mining.emission.EmissionRules -import org.ergoplatform.settings.{ErgoSettings, ReemissionSettings} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import scala.concurrent.duration._ - -class EmissionApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport { - - val prefix = "/emission/at" - - implicit val timeout: RouteTestTimeout = RouteTestTimeout(15.seconds.dilated) - - val ergoSettings: ErgoSettings = ErgoSettings.read() - val coinEmission: EmissionRules = ergoSettings.chainSettings.emissionRules - - val reemissionSettings: ReemissionSettings = ergoSettings.chainSettings.reemission - - val route: Route = EmissionApiRoute(ergoSettings).route - - it should "get correct emission values" in { - Get(prefix + "/1") ~> route ~> check { - status shouldBe StatusCodes.OK - EmissionApiRoute.emissionInfoAtHeight(1, coinEmission, reemissionSettings).asJson shouldEqual responseAs[Json] - } - - Get(prefix + "/10000") ~> route ~> check { - status shouldBe StatusCodes.OK - EmissionApiRoute.emissionInfoAtHeight(10000, coinEmission, reemissionSettings).asJson shouldEqual responseAs[Json] - } - - Get(prefix + "/1000000") ~> route ~> check { - status shouldBe StatusCodes.OK - EmissionApiRoute.emissionInfoAtHeight(1000000, coinEmission, reemissionSettings).asJson shouldEqual responseAs[Json] - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala deleted file mode 100644 index de1a6edc5d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ErgoPeersApiRouteSpec.scala +++ /dev/null @@ -1,91 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.actor.Actor -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} -import akka.testkit.{TestDuration, TestProbe} -import akka.util.Timeout -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import org.ergoplatform.http.api.ErgoPeersApiRoute -import org.ergoplatform.utils.Stubs -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers -import scorex.core.network.peer.PeerManager.ReceivableMessages.GetAllPeers -import scorex.core.settings.RESTApiSettings - -import java.net.InetSocketAddress -import scala.concurrent.Future -import scala.concurrent.duration._ - -class ErgoPeersApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport - with ScalaCheckPropertyChecks - with Stubs { - - implicit val actorTimeout: Timeout = Timeout(15.seconds.dilated) - implicit val routeTimeout: RouteTestTimeout = RouteTestTimeout(15.seconds.dilated) - - val restApiSettings = RESTApiSettings(new InetSocketAddress("localhost", 8080), None, None, 10.seconds, None) - val peerManagerProbe = TestProbe() - - it should "return all peers" in { - forAll(connectedPeerGen(Actor.noSender)) { peer => - val networkControllerProbe = TestProbe() - val route: Route = ErgoPeersApiRoute(peerManagerProbe.ref, networkControllerProbe.ref, null, null, restApiSettings).route - Future { - peerManagerProbe.expectMsg(GetAllPeers) - peerManagerProbe.reply(Map(peer.connectionId.remoteAddress -> peer.peerInfo.get)) - } - - Get("/peers/all") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received connected peers: $json") - val c = json.asArray.get.head.hcursor - c.downField("address").as[String] shouldEqual Right(peer.connectionId.remoteAddress.toString) - peer.peerInfo.get.peerSpec.publicUrlOpt.foreach { restApiUrl => - c.downField("restApiUrl").as[String] shouldEqual Right(restApiUrl.toString) - } - c.downField("lastMessage").as[Long] shouldEqual Right(0L) - c.downField("lastHandshake").as[Long] shouldEqual Right(0L) - c.downField("name").as[String] shouldEqual Right(peer.peerInfo.get.peerSpec.nodeName) - c.downField("connectionType").as[String] shouldEqual Right("Incoming") - } - } - } - - it should "return connected peers" in { - forAll(connectedPeerGen(Actor.noSender)) { peer => - val networkControllerProbe = TestProbe() - val route: Route = ErgoPeersApiRoute(peerManagerProbe.ref, networkControllerProbe.ref, null, null, restApiSettings).route - Future { - networkControllerProbe.expectMsg(GetConnectedPeers) - networkControllerProbe.reply(Seq(peer)) - } - - Get("/peers/connected") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received connected peers: $json") - val c = json.asArray.get.head.hcursor - peer.peerInfo.get.peerSpec.address.foreach { address => - c.downField("address").as[String] shouldEqual Right(address.toString) - } - peer.peerInfo.get.peerSpec.publicUrlOpt.foreach { restApiUrl => - c.downField("restApiUrl").as[String] shouldEqual Right(restApiUrl.toString) - } - c.downField("lastMessage").as[Long] shouldEqual Right(0L) - c.downField("lastHandshake").as[Long] shouldEqual Right(0L) - c.downField("name").as[String] shouldEqual Right(peer.peerInfo.get.peerSpec.nodeName) - c.downField("connectionType").as[String] shouldEqual Right("Incoming") - } - } - } -} - diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala deleted file mode 100644 index 706ff37ddd..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala +++ /dev/null @@ -1,98 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.actor.ActorRef -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} -import akka.pattern.ask -import akka.testkit.TestDuration -import akka.util.Timeout -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import org.ergoplatform.Version -import org.ergoplatform.http.api.InfoApiRoute -import org.ergoplatform.local.ErgoStatsCollector.NodeInfo.difficultyEncoder -import org.ergoplatform.local.ErgoStatsCollector.{GetNodeInfo, NodeInfo} -import org.ergoplatform.local.ErgoStatsCollectorRef -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.ChangedHistory -import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty -import org.ergoplatform.utils.Stubs -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import scala.concurrent.duration._ -import scala.concurrent.{Await, Future} - -class InfoApiRoutesSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport - with Stubs { - - implicit val actorTimeout: Timeout = Timeout(15.seconds.dilated) - implicit val routeTimeout: RouteTestTimeout = RouteTestTimeout(15.seconds.dilated) - val statsCollector: ActorRef = ErgoStatsCollectorRef(nodeViewRef, networkControllerRef, null, settings) - val route: Route = InfoApiRoute(statsCollector, settings.scorexSettings.restApi).route - val requiredDifficulty = BigInt(1) - - override def beforeAll: Unit = { - Await.ready(initDifficulty(requiredDifficulty), actorTimeout.duration) - } - - it should "return info" in { - Get("/info") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("name").as[String] shouldEqual Right(settings.scorexSettings.network.nodeName) - c.downField("appVersion").as[String] shouldEqual Right(Version.VersionString) - c.downField("stateType").as[String] shouldEqual Right(settings.nodeSettings.stateType.stateTypeName) - c.downField("isMining").as[Boolean] shouldEqual Right(settings.nodeSettings.mining) - (System.currentTimeMillis() - c.downField("launchTime").as[Long].toOption.getOrElse(0L)) < 2000 shouldBe true - c.downField("eip27Supported").as[Boolean] shouldEqual Right(true) - c.downField("restApiUrl").as[String] shouldEqual Right("https://example.com:80") - } - } - - it should "should return non-exponential difficulty in json response" in { - Get("/info") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - val res = json.toString - log.info(s"Received node info: $res") - res should include regex """\"difficulty\" : \d+,""" - } - } - - "difficulty" should "be encoded with non-exponential form " in { - val res = difficultyEncoder(requiredDifficulty) - res.toString shouldEqual requiredDifficulty.toString - } - - private def initDifficulty(difficulty: Difficulty): Future[Option[Difficulty]] = { - val emptyHistory = generateHistory( - verifyTransactions = settings.nodeSettings.verifyTransactions, - stateType = settings.nodeSettings.stateType, - poPoWBootstrap = settings.nodeSettings.nipopowSettings.nipopowBootstrap, - blocksToKeep = settings.nodeSettings.blocksToKeep - ) - val nBits = DifficultySerializer.encodeCompactBits(difficulty) - val chain = genChain(height = 5, emptyHistory, Header.InitialVersion, nBits) - val history = applyChain(emptyHistory, chain) - val generatedDifficulty = history.bestFullBlockOpt - .map(_.header.requiredDifficulty) - .map(difficultyEncoder.apply) - log.info(s"Generated difficulty: $generatedDifficulty") - statsCollector ! ChangedHistory(history) - (statsCollector ? GetNodeInfo).mapTo[NodeInfo].map { nodeInfo => - val difficulty = nodeInfo.bestFullBlockOpt.map(_.header.requiredDifficulty) - log.info(s"Set difficulty to: $difficulty") - difficulty - } - } - -} - diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/MiningApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/MiningApiRouteSpec.scala deleted file mode 100644 index dee8e45a3f..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/MiningApiRouteSpec.scala +++ /dev/null @@ -1,57 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.http.api.MiningApiRoute -import org.ergoplatform.mining.AutolykosSolution -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.Stubs -import org.ergoplatform.utils.generators.ErgoGenerators -import org.ergoplatform.{ErgoTreePredef, Pay2SAddress} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import scala.util.Try - -class MiningApiRouteSpec - extends AnyFlatSpec - with ErgoGenerators - with Matchers - with ScalatestRouteTest - with Stubs - with FailFastCirceSupport { - - val prefix = "/mining" - - val localSetting: ErgoSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(useExternalMiner = true)) - val route: Route = MiningApiRoute(minerRef, localSetting).route - - val solution = AutolykosSolution(genECPoint.sample.get, genECPoint.sample.get, Array.fill(32)(9: Byte), BigInt(0)) - - it should "return requested candidate" in { - Get(prefix + "/candidate") ~> route ~> check { - status shouldBe StatusCodes.OK - Try(responseAs[Json]) shouldBe 'success - } - } - - it should "process external solution" in { - Post(prefix + "/solution", solution.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "display miner pk" in { - Get(prefix + "/rewardAddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val script = ErgoTreePredef.rewardOutputScript(settings.chainSettings.monetary.minerRewardDelay, pk) - val addressStr = Pay2SAddress(script)(settings.addressEncoder).toString() - responseAs[Json].hcursor.downField("rewardAddress").as[String] shouldEqual Right(addressStr) - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/NipopowApiRoutesSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/NipopowApiRoutesSpec.scala deleted file mode 100644 index 2d62e20a12..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/NipopowApiRoutesSpec.scala +++ /dev/null @@ -1,82 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.{Route, ValidationRejection} -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import org.ergoplatform.http.api.NipopowApiRoute -import org.ergoplatform.utils.Stubs -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class NipopowApiRoutesSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport - with Stubs { - - private val route: Route = NipopowApiRoute(nodeViewRef, utxoReadersRef, settings).route - - it should "return proof for min superchain & suffix length" in { - Get("/nipopow/proof/1/1") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received nipopow proof response : $json") - val c = json.hcursor - c.downField("prefix").as[List[Json]].right.get shouldNot be(empty) - } - } - - it should "proof request with invalid minimum and suffix length" in { - Get("/nipopow/proof/12/24") ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "proof request with missing headerId" in { - Get("/nipopow/proof/1/1/05bf63aa1ecfc9f4e3fadc993f87b33edb4d58e151c1891816d734dd5a0e2e09") ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "proof request with invalid headerId" in { - Get("/nipopow/proof/1/1/x") ~> route ~> check { - rejection shouldEqual ValidationRejection("Wrong modifierId format", None) - } - } - - it should "return proof for min superchain & suffix length & header id" in { - val existingHeaderId = history.bestHeaderOpt.get.id - Get(s"/nipopow/proof/1/1/$existingHeaderId") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received nipopow proof response : $json") - val c = json.hcursor - c.downField("prefix").as[List[Json]].right.get shouldNot be(empty) - } - } - - it should "get popow header by id" in { - val existingHeaderId = history.bestHeaderOpt.get.id - Get(s"/nipopow/popowHeaderById/$existingHeaderId") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received popow header response : $json") - val c = json.hcursor - c.downField("interlinks").as[List[Json]].right.get shouldNot be(empty) - } - } - - it should "get popow header by height" in { - Get(s"/nipopow/popowHeaderByHeight/2") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received popow header response : $json") - val c = json.hcursor - c.downField("interlinks").as[List[Json]].right.get shouldNot be(empty) - } - } - -} - diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala deleted file mode 100644 index fb4956190f..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala +++ /dev/null @@ -1,275 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.{Route, ValidationRejection} -import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.ErgoBox -import org.ergoplatform.http.api.ScanEntities.{ScanIdBoxId, ScanIdWrapper} -import org.ergoplatform.http.api.{ApiCodecs, ScanApiRoute} -import org.ergoplatform.nodeView.wallet.scanning._ -import org.ergoplatform.settings.{Args, ErgoSettings} -import org.ergoplatform.utils.Stubs -import org.ergoplatform.wallet.Constants.ScanId -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.crypto.authds.ADKey -import scorex.utils.Random -import sigmastate.Values.ByteArrayConstant - -import scala.concurrent.duration._ -import scala.util.Try - -class ScanApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with Stubs - with FailFastCirceSupport - with ApiCodecs { - - import ScanJsonCodecs.{scanDecoder, scanReqEncoder} - import ScanIdWrapper.{scanIdWrapperEncoder, scanIdWrapperDecoder} - - implicit val timeout: RouteTestTimeout = RouteTestTimeout(145.seconds) - - val prefix = "/scan" - - val ergoSettings: ErgoSettings = ErgoSettings.read( - Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) - val route: Route = ScanApiRoute(utxoReadersRef, ergoSettings).route - - private val predicate0 = ContainsScanningPredicate(ErgoBox.R4, ByteArrayConstant(Array(0: Byte, 1: Byte))) - private val predicate1 = ContainsScanningPredicate(ErgoBox.R4, ByteArrayConstant(Array(1: Byte, 1: Byte))) - - val appRequest = ScanRequest("demo", predicate0, Some(ScanWalletInteraction.Off), Some(false)) - val appRequest2 = ScanRequest("demo2", predicate1, Some(ScanWalletInteraction.Off), None) - - it should "register a scan" in { - Post(prefix + "/register", appRequest.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - Try(responseAs[ScanIdWrapper]) shouldBe 'success - } - } - - it should "deregister a scan" in { - var scanId: ScanIdWrapper = ScanIdWrapper(ScanId @@ (-1000: Short)) // improper value - - // first, register an app - Post(prefix + "/register", appRequest.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[ScanIdWrapper]) - response shouldBe 'success - scanId = response.get - } - - // then remove it - Post(prefix + "/deregister", scanId.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - Try(responseAs[ScanIdWrapper]) shouldBe 'success - } - - // second time it should be not successful - Post(prefix + "/deregister", scanId.asJson) ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "list registered scans" in { - // register two apps - Post(prefix + "/register", appRequest.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[ScanIdWrapper]) - response shouldBe 'success - } - - Post(prefix + "/register", appRequest2.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[ScanIdWrapper]) - response shouldBe 'success - } - - Get(prefix + "/listAll") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[Seq[Scan]]) - response shouldBe 'success - val apps = response.get - - apps.map(_.scanName).contains(appRequest.scanName) shouldBe true - apps.map(_.scanName).contains(appRequest2.scanName) shouldBe true - } - } - - it should "list unspent boxes for a scan with lower constraint" in { - val minConfirmations = 15 - val minInclusionHeight = 20 - - val suffix = s"/unspentBoxes/101?minConfirmations=$minConfirmations&minInclusionHeight=$minInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe true // there are boxes that has confirmations > 15 and inclusionHeight > 20 - response.get.foreach { json => - json.hcursor.downField("confirmationsNum").as[Int].forall(_ >= minConfirmations) shouldBe true - json.hcursor.downField("inclusionHeight").as[Int].forall(_ >= minInclusionHeight) shouldBe true - } - - // unconfirmed box not returned - response.get.flatMap(_.hcursor.downField("confirmationsNum").as[Option[Int]].toOption) - .exists(_.isDefined == false) shouldBe false - } - } - - - it should "list unspent boxes for a scan with upper constraint" in { - val maxConfirmations = 15 - val maxInclusionHeight = 20 - - val suffix = s"/unspentBoxes/101?maxConfirmations=$maxConfirmations&maxInclusionHeight=$maxInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe true // there are boxes that has confirmations < 15 and inclusionHeight < 20 - response.get.foreach { json => - json.hcursor.downField("confirmationsNum").as[Int].forall(_ <= maxConfirmations) shouldBe true - json.hcursor.downField("inclusionHeight").as[Int].forall(_ <= maxInclusionHeight) shouldBe true - } - // unconfirmed box not returned - response.get.flatMap(_.hcursor.downField("confirmationsNum").as[Option[Int]].toOption) - .exists(_.isDefined == false) shouldBe false - } - } - - - it should "list unspent boxes for a scan with upper and lower constraints" in { - val confirmations = 15 - val inclusionHeight = 20 - - val suffix = s"/unspentBoxes/101?minConfirmations=$confirmations&minInclusionHeight=$inclusionHeight&maxConfirmations=$confirmations&maxInclusionHeight=$inclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe false // there are no boxes with confirmations and inclusionHeight within range - } - } - - it should "list unspent and unconfirmed boxes for a scan with lower constraint" in { - val minConfirmations = -1 - val minInclusionHeight = 0 - - val suffix = s"/unspentBoxes/101?minConfirmations=$minConfirmations&minInclusionHeight=$minInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe true - - // unconfirmed box returned - response.get.flatMap(_.hcursor.downField("confirmationsNum").as[Option[Int]].toOption) - .exists(_.isDefined == false) shouldBe true - } - } - - it should "list spent boxes for a scan with lower constraint" in { - val minConfirmations = 15 - val minInclusionHeight = 20 - - val suffix = s"/spentBoxes/101?minConfirmations=$minConfirmations&minInclusionHeight=$minInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe true - response.get.foreach { json => - json.hcursor.downField("inclusionHeight").as[Int].forall(_ >= minInclusionHeight) shouldBe true - } - response.get.foreach { json => - json.hcursor.downField("spent").as[Boolean].forall(_ == true) shouldBe true - } - - // unconfirmed box not returned - response.get.flatMap(_.hcursor.downField("confirmationsNum").as[Option[Int]].toOption) - .exists(_.isDefined == false) shouldBe false - } - } - - it should "list spent boxes for a scan with upper constraint" in { - val maxConfirmations = 15 - val maxInclusionHeight = 20 - - val suffix = s"/spentBoxes/101?maxConfirmations=$maxConfirmations&maxInclusionHeight=$maxInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe true - response.get.foreach { json => - json.hcursor.downField("confirmationsNum").as[Int].forall(_ <= maxConfirmations) shouldBe true - json.hcursor.downField("inclusionHeight").as[Int].forall(_ <= maxInclusionHeight) shouldBe true - } - response.get.foreach { json => - json.hcursor.downField("spent").as[Boolean].forall(_ == true) shouldBe true - } - - // unconfirmed box not returned - response.get.flatMap(_.hcursor.downField("confirmationsNum").as[Option[Int]].toOption) - .exists(_.isDefined == false) shouldBe false - } - } - - it should "list spent boxes boxes for a scan with upper and lower constraints" in { - val confirmations = 15 - val inclusionHeight = 20 - - val suffix = s"/spentBoxes/101?minConfirmations=$confirmations&minInclusionHeight=$inclusionHeight&maxConfirmations=$confirmations&maxInclusionHeight=$inclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = Try(responseAs[List[Json]]) - response shouldBe 'success - response.get.nonEmpty shouldBe false // there are no spent boxes with confirmations and inclusionHeight within range - } - } - - it should "fail when maxInclusionHeight is specified and we consider unconfirmed" in { - val minConfirmations = -1 - val maxInclusionHeight = 50 - - val suffix = s"/unspentBoxes/101?minConfirmations=$minConfirmations&maxInclusionHeight=$maxInclusionHeight" - - Get(prefix + suffix) ~> route ~> check { - rejection shouldEqual ValidationRejection("maxInclusionHeight cannot be specified when we consider unconfirmed") - } - } - - it should "stop tracking a box" in { - val scanIdBoxId = ScanIdBoxId(ScanId @@ (51: Short), ADKey @@ Random.randomBytes(32)) - - Post(prefix + "/stopTracking", scanIdBoxId.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "generate scan for p2s rule" in { - Post(prefix + "/p2sRule", "Ms7smJmdbakqfwNo") ~> route ~> check { - status shouldBe StatusCodes.OK - val res = responseAs[Json] - res.hcursor.downField("scanId").as[Int].toOption.isDefined shouldBe true - } - - Post(prefix + "/p2sRule", "s7smJmdbakqfwNo") ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala deleted file mode 100644 index acd2fd8de5..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala +++ /dev/null @@ -1,150 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import org.ergoplatform.{Pay2SAddress, Pay2SHAddress} -import org.ergoplatform.settings.{Args, ErgoSettings} -import org.ergoplatform.utils.Stubs -import io.circe.syntax._ -import org.ergoplatform.http.api.ScriptApiRoute -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.util.encode.Base16 -import sigmastate.SByte -import sigmastate.Values.{CollectionConstant, ErgoTree, TrueLeaf} -import sigmastate.serialization.{ErgoTreeSerializer, ValueSerializer} - - -class ScriptApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with Stubs - with FailFastCirceSupport { - - val prefix = "/script" - - val ergoSettings: ErgoSettings = ErgoSettings.read( - Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) - val route: Route = ScriptApiRoute(digestReadersRef, settings).route - - val scriptSource: String = - """ - |{ - | val myPk = PK("3WwUerNahQR1YXyq8AKi5UkKsYeJ99zxrqNqt3BCG4xSGeTERHiQ") - | HEIGHT < 9197 && myPk.isProven - |} - |""".stripMargin - - val scriptSourceSigProp: String = - """ - |{ - | PK("3WwUerNahQR1YXyq8AKi5UkKsYeJ99zxrqNqt3BCG4xSGeTERHiQ") - |} - |""".stripMargin - - it should "execute script with context" in { - val suffix = "/executeWithContext" - val stream = ClassLoader.getSystemClassLoader.getResourceAsStream("execute-script.json") - val req = scala.io.Source.fromInputStream(stream).getLines().mkString("\n") - val assertion = (json: Json) => { - status shouldBe StatusCodes.OK - val value = json.hcursor.downField("value").downField("op").as[Int].right.get - val condition = json.hcursor.downField("value").downField("condition").as[Boolean].right.get - val cost = json.hcursor.downField("cost").as[Int].right.get - value shouldEqual -45 - condition shouldEqual true - cost shouldEqual 6 - } - val json = io.circe.parser.parse(req) - Post(prefix + suffix, json) ~> route ~> check(assertion(responseAs[Json])) - } - - it should "generate valid P2SAddress form source" in { - val suffix = "/p2sAddress" - val assertion = (json: Json) => { - status shouldBe StatusCodes.OK - val addressStr = json.hcursor.downField("address").as[String].right.get - addressEncoder.fromString(addressStr).get.addressTypePrefix shouldEqual Pay2SAddress.addressTypePrefix - } - Post(prefix + suffix, Json.obj("source" -> scriptSource.asJson)) ~> route ~> check(assertion(responseAs[Json])) - Post(prefix + suffix, Json.obj("source" -> scriptSourceSigProp.asJson)) ~> route ~> - check(assertion(responseAs[Json])) - } - - it should "generate valid P2SHAddress form source" in { - val suffix = "/p2shAddress" - val assertion = (json: Json) => { - status shouldBe StatusCodes.OK - val addressStr = json.hcursor.downField("address").as[String].right.get - addressEncoder.fromString(addressStr).get.addressTypePrefix shouldEqual Pay2SHAddress.addressTypePrefix - } - Post(prefix + suffix, Json.obj("source" -> scriptSource.asJson)) ~> route ~> check(assertion(responseAs[Json])) - Post(prefix + suffix, Json.obj("source" -> scriptSourceSigProp.asJson)) ~> route ~> - check(assertion(responseAs[Json])) - } - - it should "get through address <-> ergoTree round-trip" in { - val suffix = "addressToTree" - - val assertion = (json: Json, address: String) => { - status shouldBe StatusCodes.OK - val treeStr = json.hcursor.downField("tree").as[String].right.get - - val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(Base16.decode(treeStr).get) - - val addr = addressEncoder.fromProposition(tree).get - - addressEncoder.toString(addr) shouldBe address - } - - val p2pk = "3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN" - Get(s"$prefix/$suffix/$p2pk") ~> route ~> check(assertion(responseAs[Json], p2pk)) - - val script = TrueLeaf - val tree = ErgoTree.fromProposition(script) - - val p2sh = Pay2SHAddress.apply(tree).toString() - p2sh shouldBe "rbcrmKEYduUvADj9Ts3dSVSG27h54pgrq5fPuwB" - Get(s"$prefix/$suffix/$p2sh") ~> route ~> check(assertion(responseAs[Json], p2sh)) - - val p2s = addressEncoder.toString(addressEncoder.fromProposition(tree).get) - p2s shouldBe "Ms7smJwLGbUAjuWQ" - Get(s"$prefix/$suffix/$p2s") ~> route ~> check(assertion(responseAs[Json], p2s)) - } - - it should "address <-> bytes roundtrip via addressToBytes" in { - val suffix = "addressToBytes" - - val assertion = (json: Json, address: String) => { - status shouldBe StatusCodes.OK - val vs = json.hcursor.downField("bytes").as[String].right.get - val vbs = Base16.decode(vs).get - - val bac = ValueSerializer.deserialize(vbs).asInstanceOf[CollectionConstant[SByte.type]] - - val bs = bac.value.toArray.map(_.byteValue()) - - val tree = ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bs) - - val addr = addressEncoder.fromProposition(tree).get - - addressEncoder.toString(addr) shouldBe address - } - - val p2pk = "3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN" - Get(s"$prefix/$suffix/$p2pk") ~> route ~> check(assertion(responseAs[Json], p2pk)) - - val p2sh = "rbcrmKEYduUvADj9Ts3dSVSG27h54pgrq5fPuwB" - Get(s"$prefix/$suffix/$p2sh") ~> route ~> check(assertion(responseAs[Json], p2sh)) - - val script = TrueLeaf - val tree = ErgoTree.fromProposition(script) - val p2s = addressEncoder.toString(addressEncoder.fromProposition(tree).get) - p2s shouldBe "Ms7smJwLGbUAjuWQ" - Get(s"$prefix/$suffix/$p2s") ~> route ~> check(assertion(responseAs[Json], p2s)) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala deleted file mode 100644 index 1e7860907f..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/TransactionApiRouteSpec.scala +++ /dev/null @@ -1,303 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.actor.{Actor, Props} -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.ErgoBox.{AdditionalRegisters, NonMandatoryRegisterId, TokenId} -import org.ergoplatform.http.api.{ApiCodecs, TransactionsApiRoute} -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers} -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.Stubs -import org.ergoplatform.{DataInput, ErgoBox, ErgoBoxCandidate, Input} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.core.settings.RESTApiSettings -import scorex.util.encode.Base16 -import sigmastate.SType -import sigmastate.Values.{ByteArrayConstant, EvaluatedValue} -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigma.Extensions._ - -import java.net.InetSocketAddress -import scala.concurrent.duration._ - -class TransactionApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with Stubs - with ApiCodecs - with FailFastCirceSupport { - - val prefix = "/transactions" - - val restApiSettings = RESTApiSettings(new InetSocketAddress("localhost", 8080), None, None, 10.seconds, None) - val route: Route = TransactionsApiRoute(utxoReadersRef, nodeViewRef, settings).route - - val inputBox: ErgoBox = utxoState.takeBoxes(1).head - val input = Input(inputBox.id, emptyProverResult) - val dataInput = DataInput(input.boxId) - - val absentModifierId = "0000000000000000000000000000000000000000000000000000000000000000" - val tokens = List[(TokenId, Long)](inputBox.id.toTokenId -> 10) - val registers = - Map( - ErgoBox.R4 -> ByteArrayConstant("name".getBytes("UTF-8")), - ErgoBox.R5 -> ByteArrayConstant("4".getBytes("UTF-8")), - ) - - val output: ErgoBoxCandidate = - new ErgoBoxCandidate(inputBox.value, Constants.TrueLeaf, creationHeight = 0, tokens.toColl, registers) - val tx: ErgoTransaction = ErgoTransaction(IndexedSeq(input), IndexedSeq(dataInput), IndexedSeq(output)) - - val chainedInput = Input(tx.outputs.head.id, emptyProverResult) - val chainedTx: ErgoTransaction = ErgoTransaction(IndexedSeq(chainedInput), IndexedSeq(output)) - - val chainedRoute: Route = { - //constructing memory pool and node view with the transaction tx included - val mp2 = memPool.put(UnconfirmedTransaction(tx, None)) - class UtxoReadersStub2 extends Actor { - def receive: PartialFunction[Any, Unit] = { - case GetReaders => sender() ! Readers(history, utxoState, mp2, wallet) - case GetDataFromHistory(f) => sender() ! f(history) - } - } - val readers2 = system.actorOf(Props(new UtxoReadersStub2)) - TransactionsApiRoute(readers2, nodeViewRef, settings).route - } - - it should "post transaction" in { - Post(prefix, tx.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual tx.id - } - } - - it should "fail when posting invalid transaction" in { - val failingNodeViewRef = system.actorOf(NodeViewStub.failingProps()) - val failingRoute: Route = TransactionsApiRoute(digestReadersRef, failingNodeViewRef, settings).route - - Post(prefix, tx.asJson) ~> failingRoute ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "post chained transactions" in { - Post(prefix, chainedTx.asJson) ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - - Post(prefix, tx.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual tx.id - } - - Post(prefix, chainedTx.asJson) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual chainedTx.id - } - } - - it should "check transaction" in { - Post(prefix + "/check", tx.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual tx.id - } - //second attempt should be fine also - Post(prefix + "/check", tx.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual tx.id - } - - Post(prefix + "/check", chainedTx.asJson) ~> route ~> check { - status shouldBe StatusCodes.BadRequest - } - - Post(prefix + "/check", chainedTx.asJson) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - responseAs[String] shouldEqual chainedTx.id - } - } - - it should "get unconfirmed txs from mempool" in { - Get(prefix + "/unconfirmed") ~> route ~> check { - status shouldBe StatusCodes.OK - memPool.take(50).map(_.transaction).toSeq shouldBe responseAs[Seq[ErgoTransaction]] - } - } - - it should "get unconfirmed from mempool using limit and offset" in { - val limit = 10 - val offset = 20 - Get(prefix + s"/unconfirmed?limit=$limit&offset=$offset") ~> route ~> check { - status shouldBe StatusCodes.OK - memPool.getAll.slice(offset, offset + limit).map(_.transaction) shouldBe responseAs[Seq[ErgoTransaction]] - } - } - - it should "return unconfirmed tx by output ergoTree from mempool" in { - val searchedBox = txs.head.outputs.head.ergoTree.bytesHex - Post(prefix + s"/unconfirmed/byErgoTree", searchedBox) ~> route ~> check { - val expectedTxs = memPool.getAll.toSet.filter(_.transaction.outputs.exists(_.ergoTree.bytesHex == searchedBox)) - val actualTxs = responseAs[Set[ErgoTransaction]] - status shouldBe StatusCodes.OK - expectedTxs.map(_.id) shouldBe actualTxs.map(_.id) - actualTxs.forall(tx => tx.outputs.map(_.ergoTree.bytesHex).contains(searchedBox)) shouldBe true - } - } - - it should "return unconfirmed tx by input ergoTree from mempool" in { - val searchedBox = inputBox.ergoTree.bytesHex - Post(prefix + s"/unconfirmed/byErgoTree", searchedBox) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val txs = responseAs[Set[ErgoTransaction]] - txs.forall { tx => - tx.inputs.map(_.boxId).exists(_.sameElements(inputBox.id)) || - tx.outputs.map(_.ergoTree.bytesHex).contains(searchedBox) - } shouldBe true - } - } - - it should "return unconfirmed tx by absent ergoTree from mempool" in { - Post(prefix + s"/unconfirmed/byErgoTree", absentModifierId) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Seq[ErgoTransaction]] shouldBe List.empty - } - } - - it should "return unconfirmed tx by id from mempool" in { - Get(prefix + s"/unconfirmed/byTransactionId/${txs.head.id}") ~> route ~> check { - status shouldBe StatusCodes.OK - memPool.modifierById(txs.head.id).get shouldBe responseAs[ErgoTransaction] - } - } - - it should "return unconfirmed tx by absent id from mempool" in { - Get(prefix + s"/unconfirmed/byTransactionId/$absentModifierId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - } - - it should "return 200 if unconfirmed tx is present" in { - Head(prefix + s"/unconfirmed/${txs.head.id}") ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "return 404 if unconfirmed absent tx is present" in { - Head(prefix + s"/unconfirmed/$absentModifierId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - } - - it should "return unconfirmed input by boxId from mempool" in { - val searchedBox = inputBox.id - val searchedBoxEncoded = Base16.encode(searchedBox) - Get(prefix + s"/unconfirmed/inputs/byBoxId/$searchedBoxEncoded") ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(searchedBoxEncoded) - } - } - - it should "return unconfirmed output by boxId from mempool" in { - val searchedBox = txs.head.outputs.head.id - val searchedBoxEncoded = Base16.encode(searchedBox) - Get(prefix + s"/unconfirmed/outputs/byBoxId/$searchedBoxEncoded") ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(searchedBoxEncoded) - } - } - - it should "return unconfirmed output by ergoTree from mempool" in { - val searchedBox = txs.head.outputs.head - val searchedTree = searchedBox.ergoTree.bytesHex - Post(prefix + s"/unconfirmed/outputs/byErgoTree", searchedTree) ~> route ~> check { - val expectedOutputIds = - memPool.getAll - .flatMap(_.transaction.outputs) - .filter(_.ergoTree.bytesHex == searchedTree) - .map(b => Base16.encode(b.id)).take(50).toList - status shouldBe StatusCodes.OK - val actualOutputIds = responseAs[List[Json]].map(_.hcursor.downField("boxId").as[String].right.get) - actualOutputIds shouldEqual expectedOutputIds - } - } - - it should "return unconfirmed output by tokenId from mempool" in { - val searchedToken = tokens.head._1.toHex - Get(prefix + s"/unconfirmed/outputs/byTokenId/$searchedToken") ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val actualOutputIds = responseAs[List[Json]].map(_.hcursor.downField("boxId").as[String].right.get) - actualOutputIds.nonEmpty shouldBe true - actualOutputIds shouldEqual List(Base16.encode(tx.outputs.head.id)) - } - } - - it should "return unconfirmed outputs by exact same registers" in { - val searchedRegs = - Map( - ErgoBox.R4 -> ByteArrayConstant("name".getBytes("UTF-8")), - ErgoBox.R5 -> ByteArrayConstant("4".getBytes("UTF-8")), - ).asInstanceOf[AdditionalRegisters].asJson - - Post(prefix + s"/unconfirmed/outputs/byRegisters", searchedRegs) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val actualBoxes = responseAs[List[Json]].flatMap(_.hcursor.downField("boxId").as[String].toOption) - actualBoxes.head shouldEqual Base16.encode(tx.outputs.head.id) - } - } - - it should "return unconfirmed outputs by subset of registers" in { - val searchedRegs = - Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]]( - ErgoBox.R4 -> ByteArrayConstant("name".getBytes("UTF-8")) - ).asJson - - Post(prefix + s"/unconfirmed/outputs/byRegisters", searchedRegs) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val actualBoxes = responseAs[List[Json]].flatMap(_.hcursor.downField("boxId").as[String].toOption) - actualBoxes.head shouldEqual Base16.encode(tx.outputs.head.id) - } - } - - it should "not return unconfirmed output by registers when one missing" in { - val searchedRegs = - Map( - ErgoBox.R4 -> ByteArrayConstant("name".getBytes("UTF-8")), - ErgoBox.R5 -> ByteArrayConstant("4".getBytes("UTF-8")), - ErgoBox.R6 -> ByteArrayConstant("description".getBytes("UTF-8")), - ).asInstanceOf[AdditionalRegisters].asJson - - Post(prefix + s"/unconfirmed/outputs/byRegisters", searchedRegs) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val actualBoxes = responseAs[List[Json]].flatMap(_.hcursor.downField("boxId").as[String].toOption) - actualBoxes shouldEqual List.empty - } - } - - it should "not return unconfirmed outputs by registers with only key match" in { - val searchedRegs = - Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]]( - ErgoBox.R4 -> ByteArrayConstant("foo".getBytes("UTF-8")) - ).asJson - - Post(prefix + s"/unconfirmed/outputs/byRegisters", searchedRegs) ~> chainedRoute ~> check { - status shouldBe StatusCodes.OK - val actualBoxes = responseAs[List[Json]].flatMap(_.hcursor.downField("boxId").as[String].toOption) - actualBoxes shouldEqual List.empty - } - } - - it should "not return unconfirmed outputs by empty registers" in { - val searchedRegs = Map.empty[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]].asJson - Post(prefix + s"/unconfirmed/outputs/byRegisters", searchedRegs) ~> chainedRoute ~> check { - status shouldBe StatusCodes.BadRequest - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala deleted file mode 100644 index ea4f0e01ba..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtilsApiRouteSpec.scala +++ /dev/null @@ -1,156 +0,0 @@ -package org.ergoplatform.http.routes - -import java.net.InetSocketAddress - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import org.ergoplatform.utils.Stubs -import org.ergoplatform.{P2PKAddress, Pay2SAddress, Pay2SHAddress} -import org.ergoplatform.http.api.ErgoUtilsApiRoute -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.core.settings.RESTApiSettings -import scorex.util.encode.Base16 -import sigmastate.serialization.ErgoTreeSerializer - -import scala.concurrent.duration._ - -class UtilsApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with FailFastCirceSupport - with Stubs { - - val prefix = "/utils" - - val restApiSettings = RESTApiSettings(new InetSocketAddress("localhost", 8080), None, None, 10.seconds, None) - val route: Route = ErgoUtilsApiRoute(settings).route - val p2pkaddress = P2PKAddress(defaultMinerPk) - val p2shaddress = Pay2SHAddress(feeProp) - val p2saddress = Pay2SAddress(feeProp) - - val treeSerializer: ErgoTreeSerializer = new ErgoTreeSerializer - - it should "derive address from ErgoTree (p2s)" in { - val et = Base16.encode(treeSerializer.serializeErgoTree(p2saddress.script)) - Get(s"$prefix/ergoTreeToAddress/$et") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("address").as[String] shouldEqual Right(p2saddress.toString()) - } - } - - it should "validate correct p2s address" in { - Get(s"$prefix/address/$p2saddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(p2saddress.toString()) - c.downField("isValid").as[Boolean] shouldEqual Right(true) - } - } - - it should "validate incorrect address (p2s)" in { - val invalidAddress = p2saddress + "aa" - Get(s"$prefix/address/$invalidAddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(invalidAddress) - c.downField("isValid").as[Boolean] shouldEqual Right(false) - c.downField("error").as[String] shouldEqual Right("requirement failed: Trying to decode mainnet address in testnet") - } - } - - //p2sh - - it should "derive address from ErgoTree (p2sh)" in { - val et = Base16.encode(treeSerializer.serializeErgoTree(p2shaddress.script)) - Get(s"$prefix/ergoTreeToAddress/$et") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("address").as[String] shouldEqual Right(p2shaddress.toString()) - } - } - - it should "validate correct p2sh address" in { - Get(s"$prefix/address/$p2shaddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(p2shaddress.toString()) - c.downField("isValid").as[Boolean] shouldEqual Right(true) - } - } - - it should "validate incorrect address (p2sh)" in { - val invalidAddress = p2shaddress + "aa" - Get(s"$prefix/address/$invalidAddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(invalidAddress) - c.downField("isValid").as[Boolean] shouldEqual Right(false) - c.downField("error").as[String] shouldEqual Right("requirement failed: Trying to decode mainnet address in testnet") - } - } - - //p2pk - - it should "do correct raw/address roundtrip (p2pk)" in { - var raw: String = null - - Get(s"$prefix/addressToRaw/$p2pkaddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - val c = json.hcursor - raw = c.downField("raw").as[String].toOption.get - } - - Get(s"$prefix/rawToAddress/$raw") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(p2pkaddress.toString()) - } - } - - it should "derive address from ErgoTree (p2pk)" in { - val et = Base16.encode(treeSerializer.serializeErgoTree(p2pkaddress.script)) - Get(s"$prefix/ergoTreeToAddress/$et") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("address").as[String] shouldEqual Right(p2pkaddress.toString()) - } - } - - it should "validate correct p2pk address" in { - Get(s"$prefix/address/$p2pkaddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(p2pkaddress.toString()) - c.downField("isValid").as[Boolean] shouldEqual Right(true) - } - } - - it should "validate incorrect address (p2pk)" in { - val invalidAddress = p2pkaddress + "aa" - Get(s"$prefix/address/$invalidAddress") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received node info: $json") - val c = json.hcursor - c.downField("address").as[String] shouldEqual Right(invalidAddress) - c.downField("isValid").as[Boolean] shouldEqual Right(false) - c.downField("error").as[String] shouldEqual Right("requirement failed: Trying to decode mainnet address in testnet") - } - } - -} - diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtxoApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtxoApiRouteSpec.scala deleted file mode 100644 index b5a2fa391b..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/UtxoApiRouteSpec.scala +++ /dev/null @@ -1,125 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route -import akka.http.scaladsl.testkit.ScalatestRouteTest -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.Json -import io.circe.syntax._ -import org.ergoplatform.http.api.{ApiCodecs, UtxoApiRoute} -import org.ergoplatform.utils.Stubs -import org.ergoplatform.wallet.boxes.ErgoBoxSerializer -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import scorex.crypto.hash.Blake2b256 -import scorex.util.encode.Base16 - -class UtxoApiRouteSpec - extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with Stubs - with FailFastCirceSupport - with ApiCodecs { - - val prefix = "/utxo" - - val route: Route = - UtxoApiRoute(utxoReadersRef, utxoSettings.scorexSettings.restApi).route - - it should "get utxo box with /byId" in { - val box = utxoState.takeBoxes(1).head - val boxId = Base16.encode(box.id) - Get(prefix + s"/byId/$boxId") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("value").as[Long] shouldEqual Right(box.value) - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(boxId) - } - } - - it should "get mempool box with withPool/byId" in { - val box = memPool.getAll.map(utx => utx.transaction).flatMap(_.outputs).head - val boxId = Base16.encode(box.id) - Get(prefix + s"/byId/$boxId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - Get(prefix + s"/withPool/byId/$boxId") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("value").as[Long] shouldEqual Right(box.value) - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(boxId) - } - } - - it should "get all mempool boxes with withPool/byIds" in { - val boxes = memPool.getAll.map(utx => utx.transaction).flatMap(_.outputs) - val boxesEncoded = boxes.map(box => Base16.encode(box.id)) - - Post(prefix + "/withPool/byIds", boxesEncoded.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Seq[Json]] - .map(_.hcursor.downField("value").as[Long]) shouldEqual boxes.map(x => Right(x.value)) - responseAs[Seq[Json]] - .map(_.hcursor.downField("boxId").as[String]) shouldEqual boxesEncoded.map(x => Right(x)) - } - } - - it should "not found utxo box with /byId" in { - val boxId = Base16.encode(Blake2b256(utxoState.takeBoxes(1).head.id)) - Get(prefix + s"/byId/$boxId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - } - - it should "get utxo box with /byIdBinary" in { - val box = utxoState.takeBoxes(1).head - val boxId = Base16.encode(box.id) - Get(prefix + s"/byIdBinary/$boxId") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(boxId) - val bytes = Base16 - .decode(responseAs[Json].hcursor.downField("bytes").as[String].toOption.get) - .get - val boxRestored = ErgoBoxSerializer.parseBytes(bytes) - box shouldEqual boxRestored - } - } - - it should "not found utxo box with /byIdBinary" in { - val boxId = Base16.encode(Blake2b256(utxoState.takeBoxes(1).head.id)) - Get(prefix + s"/byId/$boxId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - } - - it should "get pool box with /withPool/byIdBinary" in { - val box = memPool.getAll.map(utx => utx.transaction).flatMap(_.outputs).head - val boxId = Base16.encode(box.id) - Get(prefix + s"/byIdBinary/$boxId") ~> route ~> check { - status shouldBe StatusCodes.NotFound - } - Get(prefix + s"/withPool/byIdBinary/$boxId") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("boxId").as[String] shouldEqual Right(boxId) - val bytes = Base16 - .decode(responseAs[Json].hcursor.downField("bytes").as[String].toOption.get) - .get - val boxRestored = ErgoBoxSerializer.parseBytes(bytes) - box shouldEqual boxRestored - } - } - - it should "/genesis returns 3 boxes" in { - Get(prefix + s"/genesis") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 3 // 3 genesis boxes as per Ergo Whitepaper - } - } - - it should "get serialized proof for given boxes" in { - val boxes = utxoState.takeBoxes(10).map(box => Base16.encode(box.id)) - Post(prefix + s"/getBoxesBinaryProof", boxes.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala deleted file mode 100644 index 3aa73d9dc1..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala +++ /dev/null @@ -1,314 +0,0 @@ -package org.ergoplatform.http.routes - -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.{Route, ValidationRejection} -import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} -import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport -import io.circe.syntax._ -import io.circe.{Decoder, Json} -import org.ergoplatform.http.api.{ApiCodecs, WalletApiRoute} -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequestEncoder, PaymentRequest, PaymentRequestEncoder, _} -import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, ErgoAddressJsonEncoder} -import org.ergoplatform.settings.{Args, Constants, ErgoSettings} -import org.ergoplatform.utils.Stubs -import org.ergoplatform.utils.generators.ErgoTransactionGenerators -import org.ergoplatform.{ErgoAddress, Pay2SAddress} -import org.ergoplatform.wallet.{Constants => WalletConstants} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import scala.util.{Random, Try} -import scala.concurrent.duration._ -import akka.http.scaladsl.server.MissingQueryParamRejection - -class WalletApiRouteSpec extends AnyFlatSpec - with Matchers - with ScalatestRouteTest - with Stubs - with FailFastCirceSupport - with ApiCodecs { - - implicit val timeout: RouteTestTimeout = RouteTestTimeout(145.seconds) - - val prefix = "/wallet" - - val ergoSettings: ErgoSettings = ErgoSettings.read( - Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) - val route: Route = WalletApiRoute(digestReadersRef, nodeViewRef, settings).route - val failingNodeViewRef = system.actorOf(NodeViewStub.failingProps()) - val failingRoute: Route = WalletApiRoute(digestReadersRef, failingNodeViewRef, settings).route - - val utxoRoute: Route = WalletApiRoute(utxoReadersRef, nodeViewRef, settings).route - - implicit val paymentRequestEncoder: PaymentRequestEncoder = new PaymentRequestEncoder(ergoSettings) - implicit val assetIssueRequestEncoder: AssetIssueRequestEncoder = new AssetIssueRequestEncoder(ergoSettings) - implicit val requestsHolderEncoder: RequestsHolderEncoder = new RequestsHolderEncoder(ergoSettings) - implicit val addressJsonDecoder: Decoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).decoder - - val paymentRequest = PaymentRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), 100L, Seq.empty, Map.empty) - val assetIssueRequest = AssetIssueRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), None, 100L, "TEST", "Test", 8) - val requestsHolder = RequestsHolder( - (0 to 10).flatMap(_ => Seq(paymentRequest, assetIssueRequest)), - Some(10000L), - Seq.empty, - Seq.empty, - minerRewardDelay = 720 - )(addressEncoder) - - - it should "generate arbitrary transaction" in { - Post(prefix + "/transaction/generate", requestsHolder.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - Try(responseAs[ErgoTransaction]) shouldBe 'success - } - } - - it should "get balances" in { - Get(prefix + "/balances") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received balances: $json") - val c = json.hcursor - c.downField("balance").as[Long] shouldEqual Right(WalletActorStub.confirmedBalance) - } - } - - it should "get unconfirmed balances" in { - Get(prefix + "/balances/withUnconfirmed") ~> route ~> check { - status shouldBe StatusCodes.OK - val json = responseAs[Json] - log.info(s"Received total confirmed with unconfirmed balances: $json") - val c = json.hcursor - c.downField("balance").as[Long] shouldEqual Right(WalletActorStub.unconfirmedBalance) - } - } - - it should "generate & send arbitrary transaction" in { - Post(prefix + "/transaction/send", requestsHolder.asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] should not be empty - } - } - - it should "fail when sent transaction is invalid" in { - Post(prefix + "/transaction/send", requestsHolder.asJson) ~> failingRoute ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "sign a transaction" in { - val digest = Random.nextBoolean() - val (tsr, r) = if (digest) { - (ErgoTransactionGenerators.transactionSigningRequestGen(true).sample.get, route) - } else { - (ErgoTransactionGenerators.transactionSigningRequestGen(utxoState).sample.get, utxoRoute) - } - Post(prefix + "/transaction/sign", tsr.asJson) ~> r ~> check { - status shouldBe StatusCodes.OK - responseAs[ErgoTransaction].id shouldBe tsr.unsignedTx.id - } - } - - it should "generate & send payment transaction" in { - Post(prefix + "/payment/send", Seq(paymentRequest).asJson) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[String] should not be empty - } - } - - it should "fail when payment is invalid" in { - Post(prefix + "/payment/send", Seq(paymentRequest).asJson) ~> failingRoute ~> check { - status shouldBe StatusCodes.BadRequest - } - } - - it should "return addresses" in { - Get(prefix + "/addresses") ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "initialize wallet" in { - Post(prefix + "/init", Json.obj("pass" -> "1234".asJson)) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("mnemonic").as[String] shouldEqual Right(WalletActorStub.mnemonic) - } - } - - it should "restore wallet" in { - Post(prefix + "/restore", Json.obj("pass" -> "1234".asJson, "mnemonic" -> WalletActorStub.mnemonic.asJson, - "usePre1627KeyDerivation" -> false.asJson)) ~> - route ~> check(status shouldBe StatusCodes.OK) - } - - it should "not restore wallet without key derivation method specified" in { - Post(prefix + "/restore", Json.obj("pass" -> "1234".asJson, "mnemonic" -> WalletActorStub.mnemonic.asJson)) ~> - route ~> check(rejection shouldBe a[MissingQueryParamRejection]) - } - - it should "unlock wallet" in { - Post(prefix + "/unlock", Json.obj("pass" -> "1234".asJson)) ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "check wallet" in { - Post(prefix + "/check", Json.obj("mnemonic" -> WalletActorStub.mnemonic.asJson)) ~> - route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("matched").as[Boolean] shouldBe Right(true) - } - } - - it should "lock wallet" in { - Get(prefix + "/lock") ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "rescan wallet post" in { - Post(prefix + "/rescan") ~> route ~> check { - status shouldBe StatusCodes.OK - } - } - - it should "rescan wallet post with fromHeight" in { - Post(prefix + "/rescan", Json.obj("fromHeight" -> 0.asJson)) ~> route ~> check { - status shouldBe StatusCodes.OK - } - - Post(prefix + "/rescan", Json.obj("fromHeight" -> (-1).asJson)) ~> route ~> check { - rejection shouldEqual ValidationRejection("fromHeight field must be >= 0", None) - } - } - - it should "derive new key according to a provided path" in { - Post(prefix + "/deriveKey", Json.obj("derivationPath" -> "m/1/2".asJson)) ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("address").as[String] shouldEqual Right(WalletActorStub.address.toString) - } - } - - it should "derive next key" in { - Get(prefix + "/deriveNextKey") ~> route ~> check { - status shouldBe StatusCodes.OK - responseAs[Json].hcursor.downField("derivationPath").as[String] shouldEqual Right(WalletActorStub.path.encoded) - responseAs[Json].hcursor.downField("address").as[String] shouldEqual Right(WalletActorStub.address.toString) - } - } - - it should "return wallet boxes" in { - Get(prefix + "/boxes") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 3 - } - } - - it should "return wallet boxes with lower constraint" in { - val minConfirmations = 15 - val minInclusionHeight = 20 - val postfix = s"/boxes?minConfirmations=$minConfirmations&minInclusionHeight=$minInclusionHeight" - Get(prefix + postfix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 2 - response.head.hcursor.downField("confirmationsNum").as[Int].forall(_ >= minConfirmations) shouldBe true - response.head.hcursor.downField("inclusionHeight").as[Int].forall(_ >= minInclusionHeight) shouldBe true - } - } - - it should "return wallet boxes with upper constraint" in { - val maxConfirmations = 15 - val maxInclusionHeight = 20 - val postfix = s"/boxes?maxConfirmations=$maxConfirmations&maxInclusionHeight=$maxInclusionHeight" - Get(prefix + postfix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 1 - response.head.hcursor.downField("confirmationsNum").as[Int].forall(_ <= maxConfirmations) shouldBe true - response.head.hcursor.downField("inclusionHeight").as[Int].forall(_ <= maxInclusionHeight) shouldBe true - } - } - - it should "return wallet boxes with both lower and upper constraint" in { - val confirmations = 15 - val inclusionHeight = 20 - val postfix = s"/boxes?$confirmations&minInclusionHeight=$inclusionHeight&maxConfirmations=$confirmations&maxInclusionHeight=$inclusionHeight" - Get(prefix + postfix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.isEmpty shouldBe true - } - } - - it should "return unspent wallet boxes" in { - val minConfirmations = 15 - val minInclusionHeight = 20 - - val postfix = s"/boxes/unspent?minConfirmations=$minConfirmations&minInclusionHeight=$minInclusionHeight" - - Get(prefix + postfix) ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 1 - response.head.hcursor.downField("confirmationsNum").as[Int].forall(_ >= minConfirmations) shouldBe true - response.head.hcursor.downField("inclusionHeight").as[Int].forall(_ >= minInclusionHeight) shouldBe true - } - - Get(prefix + "/boxes/unspent") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - response.size shouldBe 2 - } - } - - it should "return wallet transactions" in { - Get(prefix + "/transactions") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[List[Json]] - val walletTxs = WalletActorStub.walletTxs.filter { awtx => - awtx.wtx.scanIds.exists(_ <= WalletConstants.PaymentsScanId) - } - - response.size shouldBe walletTxs.size - responseAs[Seq[AugWalletTransaction]] shouldEqual walletTxs - } - } - - it should "return wallet transactions by scanId" in { - Get(prefix + "/transactionsByScanId/1") ~> route ~> check { - import AugWalletTransaction._ - status shouldBe StatusCodes.OK - val response = responseAs[List[AugWalletTransaction]] - val walletTxs = response.filter { awtx => - awtx.wtx.scanIds.contains(1.shortValue()) - } - walletTxs.size shouldBe response.size - } - } - - it should "return wallet transactions by scanId including unconfirmed txs" in { - Get(prefix + "/transactionsByScanId/1?includeUnconfirmed=true") ~> route ~> check { - import AugWalletTransaction._ - status shouldBe StatusCodes.OK - val response = responseAs[List[AugWalletTransaction]] - val walletTxs = response.filter { awtx => - awtx.wtx.scanIds.contains(1.shortValue()) - } - walletTxs.size shouldBe response.size - walletTxs.forall(_.numConfirmations == 0) shouldBe true - } - } - - it should "get lock status" in { - Get(prefix + "/status") ~> route ~> check { - status shouldBe StatusCodes.OK - val response = responseAs[Json] - response.hcursor.downField("isUnlocked").as[Boolean] shouldBe Right(true) - response.hcursor.downField("isInitialized").as[Boolean] shouldBe Right(true) - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala deleted file mode 100644 index f018569c5e..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala +++ /dev/null @@ -1,121 +0,0 @@ -package org.ergoplatform.local - -import akka.actor.{ActorRef, ActorSystem} -import akka.testkit.{TestActorRef, TestProbe} -import org.ergoplatform.ErgoAddressEncoder -import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{FailedTransaction, RecheckMempool, SuccessfulTransaction} -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{LocallyGeneratedTransaction, RecheckedTransactions} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome -import org.ergoplatform.nodeView.state.ErgoState -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.settings.{Algos, Constants, ErgoSettings} -import org.ergoplatform.utils.fixtures.NodeViewFixture -import org.ergoplatform.utils.{ErgoTestHelpers, MempoolTestHelpers, NodeViewTestOps, RandomWrapper} -import org.scalatest.flatspec.AnyFlatSpec -import scorex.core.network.NetworkController.ReceivableMessages.SendToNetwork -import sigmastate.Values.ErgoTree -import sigmastate.eval.{IRContext, RuntimeIRContext} -import sigmastate.interpreter.Interpreter.emptyEnv -import sigmastate.lang.SigmaCompiler -import sigmastate.lang.Terms.ValueOps -import sigmastate.serialization.ErgoTreeSerializer - -import scala.concurrent.duration._ - -class MempoolAuditorSpec extends AnyFlatSpec with NodeViewTestOps with ErgoTestHelpers with MempoolTestHelpers { - implicit lazy val context: IRContext = new RuntimeIRContext - - val cleanupDuration: FiniteDuration = 200.millis - val settingsToTest: ErgoSettings = settings.copy( - nodeSettings = settings.nodeSettings.copy( - mempoolCleanupDuration = cleanupDuration, - rebroadcastCount = 1 - )) - val fixture = new NodeViewFixture(settingsToTest, parameters) - val newTx: Class[SuccessfulTransaction] = classOf[SuccessfulTransaction] - - it should "remove transactions which become invalid" in { - import fixture._ - - val testProbe = new TestProbe(actorSystem) - actorSystem.eventStream.subscribe(testProbe.ref, newTx) - - val (us, bh) = createUtxoState(settingsToTest) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, settingsToTest, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - } .get - - applyBlock(genesis) shouldBe 'success - getRootHash shouldBe Algos.encode(wusAfterGenesis.rootDigest) - - val boxes = ErgoState.newBoxes(genesis.transactions).find(_.ergoTree == Constants.TrueLeaf) - boxes.nonEmpty shouldBe true - - val script = s"{sigmaProp(HEIGHT == ${genesis.height} + 1)}" - val compiler = new SigmaCompiler(ErgoAddressEncoder.MainnetNetworkPrefix) - val prop = compiler.compile(emptyEnv, script).buildTree - val tree = ErgoTree.fromProposition(prop.asSigmaProp) - - val bs = ErgoTreeSerializer.DefaultSerializer.serializeErgoTree(tree) - ErgoTreeSerializer.DefaultSerializer.deserializeErgoTree(bs) shouldBe tree - - val validTx = validTransactionFromBoxes(boxes.toIndexedSeq, outputsProposition = tree) - - val temporarilyValidTx = validTransactionFromBoxes(validTx.outputs, outputsProposition = proveDlogGen.sample.get) - - subscribeEvents(classOf[FailedTransaction]) - nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(validTx, None)) - testProbe.expectMsgClass(cleanupDuration, newTx) - expectMsgType[ProcessingOutcome.Accepted] - - nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(temporarilyValidTx, None)) - testProbe.expectMsgClass(cleanupDuration, newTx) - expectMsgType[ProcessingOutcome.Accepted] - - getPoolSize shouldBe 2 - - val _: ActorRef = MempoolAuditorRef(nodeViewHolderRef, nodeViewHolderRef, settingsToTest) - - Thread.sleep(200) // give transactions in the pool enough time to become candidates for re-checking - - // include first transaction in the block - val block = validFullBlock(Some(genesis), wusAfterGenesis, Seq(validTx)) - - applyBlock(block) shouldBe 'success - - scorex.core.utils.untilTimeout(cleanupDuration * 4, 100.millis) { - // first tx removed from pool during node view update - // another tx invalidated by `MempoolAuditor` - getPoolSize shouldBe 0 - } - } - - it should "rebroadcast transactions correctly" in { - - val (us0, bh0) = createUtxoState(settingsToTest) - val (txs0, bh1) = validTransactionsFromBoxHolder(bh0) - val b1 = validFullBlock(None, us0, txs0) - - val us = us0.applyModifier(b1, None)(_ => ()).get - - val bxs = bh1.boxes.values.toList.filter(_.proposition != genesisEmissionBox.proposition) - val txs = validTransactionsFromBoxes(200000, bxs, new RandomWrapper)._1 - .map(tx => UnconfirmedTransaction(tx, None)) - - implicit val system = ActorSystem() - val probe = TestProbe() - - val auditor: ActorRef = TestActorRef(new MempoolAuditor(probe.ref, probe.ref, settingsToTest)) - - - auditor ! RecheckMempool(us, new FakeMempool(txs)) - - probe.fishForMessage(3.seconds) { - case _: SendToNetwork => true - case _: RecheckedTransactions => false - }.isInstanceOf[SendToNetwork] shouldBe true - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/local/NipopowVerifierSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/local/NipopowVerifierSpec.scala deleted file mode 100644 index 21e13f95a6..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/local/NipopowVerifierSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -package org.ergoplatform.local - -import org.ergoplatform.modifiers.history.popow.{PoPowHeader, PoPowParams} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.utils.generators.{ChainGenerator, ErgoGenerators} -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec - - -class NipopowVerifierSpec extends AnyPropSpec with Matchers with ChainGenerator with ErgoGenerators { - - private val poPowParams = PoPowParams(30, 30, continuous = false) - val toPoPoWChain = (c: Seq[ErgoFullBlock]) => c.map(b => PoPowHeader.fromBlock(b).get) - - property("processes new proofs") { - val sizes = Seq(1000) - sizes.foreach { size => - val baseChain = genChain(size) - val branchPoint = baseChain.last - val shortChain = toPoPoWChain(baseChain) - val longChain = toPoPoWChain(baseChain ++ genChain(5, branchPoint).tail) - val longestChain = toPoPoWChain(baseChain ++ genChain(50, branchPoint).tail) - - val shortProof = nipopowAlgos.prove(shortChain)(poPowParams).get - val longProof = nipopowAlgos.prove(longChain)(poPowParams).get - val longestProof = nipopowAlgos.prove(longestChain)(poPowParams).get - - val verifier = new NipopowVerifier(Some(baseChain.head.id)) - verifier.bestChain.length shouldBe 0 - - verifier.process(shortProof) - verifier.bestChain.length should be > 0 - - verifier.process(longProof) - verifier.bestChain.last.id shouldBe longProof.headersChain.last.id - - verifier.process(longestProof) - verifier.bestChain.last.id shouldBe longestProof.headersChain.last.id - - verifier.process(shortProof) - verifier.bestChain.last.id shouldBe longestProof.headersChain.last.id - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala deleted file mode 100644 index 173623f510..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/AutolykosPowSchemeSpec.scala +++ /dev/null @@ -1,132 +0,0 @@ -package org.ergoplatform.mining - -import com.google.common.primitives.Ints -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.Gen -import scorex.crypto.hash.Blake2b256 -import scorex.testkit.utils.NoShrink -import scorex.util.encode.Base16 - -class AutolykosPowSchemeSpec extends ErgoPropertyTest with NoShrink { - - property("generated solution should be valid") { - val pow = new AutolykosPowScheme(powScheme.k, powScheme.n) - forAll(invalidHeaderGen, - Gen.choose(100, 120), - Gen.choose[Byte](1, 2)) { (inHeader, difficulty, ver) => - val nBits = DifficultySerializer.encodeCompactBits(difficulty) - val h = inHeader.copy(nBits = nBits, version = ver) - val sk = randomSecret() - val x = randomSecret() - val msg = pow.msgByHeader(h) - val b = pow.getB(h.nBits) - val hbs = Ints.toByteArray(h.height) - val N = pow.calcN(h) - val newHeader = pow.checkNonces(ver, hbs, msg, sk, x, b, N, 0, 1000) - .map(s => h.copy(powSolution = s)).get - pow.validate(newHeader) shouldBe 'success - - if(ver > Header.InitialVersion) { - // We remove last byte of "msg", perform PoW and check that it fails validation - require(HeaderSerializer.bytesWithoutPow(h).last == 0) - val msg2 = Blake2b256(HeaderSerializer.bytesWithoutPow(h).dropRight(1)) - - val newHeader2 = pow.checkNonces(ver, hbs, msg2, sk, x, b, N, 0, 1000) - .map(s => h.copy(powSolution = s)).get - pow.validate(newHeader2) shouldBe 'failure - } - } - } - - property("calcN test vectors") { - // mainnet parameters - val k = 32 - val n = 26 - - val pow = new AutolykosPowScheme(k, n) - - // N is always the same in Autolykos v1 - pow.calcN(1, 700000) shouldBe pow.NBase - pow.calcN(1, 100000) shouldBe pow.NBase - pow.calcN(1, 70000000) shouldBe pow.NBase - - pow.calcN(2, 500000) shouldBe pow.NBase - pow.calcN(2, 600000) shouldBe pow.NBase - pow.calcN(2, 600 * 1024) shouldBe 70464240 - pow.calcN(2, 650 * 1024) shouldBe 73987410 - pow.calcN(2, 700000) shouldBe 73987410 - pow.calcN(2, 788400) shouldBe 81571035 // 3 years - pow.calcN(2, 1051200) shouldBe 104107290 // 4 years - pow.calcN(2, 4198400) shouldBe 2143944600 // max height - pow.calcN(2, 41984000) shouldBe 2143944600 - } - - property("test vectors for first increase in N value (height 614,400)") { - import io.circe.parser._ - val pow = new AutolykosPowScheme(32, 26) - - val headerJson = - """ - |{ - | "extensionId" : "00cce45975d87414e8bdd8146bc88815be59cd9fe37a125b5021101e05675a18", - | "difficulty" : "16384", - | "votes" : "000000", - | "timestamp" : 4928911477310178288, - | "size" : 223, - | "stateRoot" : "5c8c00b8403d3701557181c8df800001b6d5009e2201c6ff807d71808c00019780", - | "height" : 614400, - | "nBits" : 37748736, - | "version" : 2, - | "id" : "5603a937ec1988220fc44fb5022fb82d5565b961f005ebb55d85bd5a9e6f801f", - | "adProofsRoot" : "5d3f80dcff7f5e7f59007294c180808d0158d1ff6ba10000f901c7f0ef87dcff", - | "transactionsRoot" : "f17fffacb6ff7f7f1180d2ff7f1e24ffffe1ff937f807f0797b9ff6ebdae007e", - | "extensionHash" : "1480887f80007f4b01cf7f013ff1ffff564a0000b9a54f00770e807f41ff88c0", - | "powSolutions" : { - | "pk" : "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c", - | "n" : "0000000000003105" - | }, - | "adProofsId" : "dec129290a763f4de41f04e87e2b661dd59758af6bdd00dd51f5d97c3a8cb9b5", - | "transactionsId" : "eba1dd82cf51147232e09c1f72b37c554c30f63274d5093bff36849a83472a42", - | "parentId" : "ac2101807f0000ca01ff0119db227f202201007f62000177a080005d440896d0" - |} - """.stripMargin - - val header = Header.jsonDecoder.decodeJson(parse(headerJson).toOption.get).toOption.get - - header.height shouldBe 614400 - - val msg = Base16.encode(pow.msgByHeader(header)) - msg shouldBe "548c3e602a8f36f8f2738f5f643b02425038044d98543a51cabaa9785e7e864f" - - pow.calcN(header) shouldBe 70464240 - - // vector got from a miner dev - pow.hitForVersion2(header) shouldBe toBigInt(Base16.decode("0002fcb113fe65e5754959872dfdbffea0489bf830beb4961ddc0e9e66a1412a").get) - - pow.getB(header.nBits) shouldBe BigInt("7067388259113537318333190002971674063283542741642755394446115914399301849") - - Base16.encode(groupElemToBytes(header.powSolution.pk)) shouldBe "03bedaee069ff4829500b3c07c4d5fe6b3ea3d3bf76c5c28c1d4dcdb1bed0ade0c" - - Base16.encode(header.powSolution.n) shouldBe "0000000000003105" - - pow.validate(header) shouldBe 'success - } - - // testing an invalid header got from a mining pool - property("test vector - invalid solution") { - import io.circe.parser._ - - val headerJson = "{\"extensionId\":\"277907e4e5e42f27e928e6101cc4fec173bee5d7728794b73d7448c339c380e5\",\"difficulty\":\"1325481984\",\"votes\":\"000000\",\"timestamp\":1611225263165,\"size\":219,\"stateRoot\":\"c0d0b5eafd07b22487dac66628669c42a242b90bef3e1fcdc76d83140d58b6bc0e\",\"height\":2870,\"nBits\":72286528,\"version\":2,\"id\":\"5b0ce6711de6b926f60b67040cc4512804517785df375d063f1bf1d75588af3a\",\"adProofsRoot\":\"49453875a43035c7640dee2f905efe06128b00d41acd2c8df13691576d4fd85c\",\"transactionsRoot\":\"770cbb6e18673ed025d386487f15d3252115d9a6f6c9b947cf3d04731dd6ab75\",\"extensionHash\":\"9bc7d54583c5d44bb62a7be0473cd78d601822a626afc13b636f2cbff0d87faf\",\"powSolutions\":{\"pk\":\"0288114b0586efea9f86e4587f2071bc1c85fb77e15eba96b2769733e0daf57903\",\"w\":\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\",\"n\":\"000100000580a91b\",\"d\":0},\"adProofsId\":\"4fc36d59bf26a672e01fbfde1445bd66f50e0f540f24102e1e27d0be1a99dfbf\",\"transactionsId\":\"d196ef8a7ef582ab1fdab4ef807715183705301c6ae2ff0dcbe8f1d577ba081f\",\"parentId\":\"ab19e6c7a4062979dddb534df83f236d1b949c7cef18bcf434a67e87c593eef9\"}" - - val json = parse(headerJson).toOption.get - - val header = Header.jsonDecoder.decodeJson(json).toOption.get - - val pow = new AutolykosPowScheme(32, 26) - - pow.validate(header).isSuccess shouldBe false - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala deleted file mode 100644 index 1c666e18e4..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala +++ /dev/null @@ -1,289 +0,0 @@ -package org.ergoplatform.mining - -import org.ergoplatform.ErgoTreePredef -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.ErgoStateContext -import org.ergoplatform.settings.MonetarySettings -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.wallet.interpreter.ErgoInterpreter -import org.scalacheck.Gen -import sigmastate.crypto.DLogProtocol.ProveDlog - -import scala.concurrent.duration._ - -class CandidateGeneratorPropSpec extends ErgoPropertyTest { - - val delta: Int = settings.chainSettings.monetary.minerRewardDelay - - private def expectedRewardOutputScriptBytes(pk: ProveDlog): Array[Byte] = - ErgoTreePredef.rewardOutputScript(delta, pk).bytes - - implicit private val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - - property("minersRewardAtHeight test vectors") { - emission.minersRewardAtHeight(525000) shouldBe 67500000000L - emission.minersRewardAtHeight(525600) shouldBe 67500000000L - emission.minersRewardAtHeight(590400) shouldBe 67500000000L - emission.minersRewardAtHeight(655200) shouldBe 66000000000L - emission.minersRewardAtHeight(720000) shouldBe 63000000000L - emission.minersRewardAtHeight(784800) shouldBe 60000000000L - emission.minersRewardAtHeight(849600) shouldBe 57000000000L - emission.minersRewardAtHeight(914400) shouldBe 54000000000L - emission.minersRewardAtHeight(979200) shouldBe 51000000000L - emission.minersRewardAtHeight(1044000) shouldBe 48000000000L - emission.minersRewardAtHeight(1108800) shouldBe 45000000000L - emission.minersRewardAtHeight(1173600) shouldBe 42000000000L - emission.minersRewardAtHeight(1238400) shouldBe 39000000000L - emission.minersRewardAtHeight(1303200) shouldBe 36000000000L - emission.minersRewardAtHeight(1368000) shouldBe 33000000000L - emission.minersRewardAtHeight(1432800) shouldBe 30000000000L - emission.minersRewardAtHeight(1497600) shouldBe 27000000000L - emission.minersRewardAtHeight(1562400) shouldBe 24000000000L - emission.minersRewardAtHeight(1627200) shouldBe 21000000000L - emission.minersRewardAtHeight(1692000) shouldBe 18000000000L - emission.minersRewardAtHeight(1756800) shouldBe 15000000000L - emission.minersRewardAtHeight(1821600) shouldBe 12000000000L - emission.minersRewardAtHeight(1886400) shouldBe 9000000000L - emission.minersRewardAtHeight(1951200) shouldBe 6000000000L - emission.minersRewardAtHeight(2016000) shouldBe 3000000000L - emission.minersRewardAtHeight(2080799) shouldBe 3000000000L - emission.minersRewardAtHeight(2080800) shouldBe 0L - } - - property("collect reward from emission box only") { - val us = createUtxoState(settings)._1 - us.emissionBoxOpt should not be None - val expectedReward = emission.minersRewardAtHeight(us.stateContext.currentHeight) - - val incorrectTxs = - CandidateGenerator.collectEmission(us, proveDlogGen.sample.get, emptyStateContext).toSeq - val txs = CandidateGenerator.collectEmission(us, defaultMinerPk, emptyStateContext).toSeq - - txs.size shouldBe 1 - val emissionTx = txs.head - emissionTx.outputs.length shouldBe 2 - emissionTx.outputs.last.value shouldBe expectedReward - emissionTx.outputs.last.propositionBytes shouldEqual expectedRewardOutputScriptBytes( - defaultMinerPk - ) - - us.applyModifier(validFullBlock(None, us, incorrectTxs), None)(_ => ()) shouldBe 'failure - us.applyModifier(validFullBlock(None, us, txs), None)(_ => ()) shouldBe 'success - } - - property("collect reward from transaction fees only") { - val bh = boxesHolderGen.sample.get - val us = createUtxoState(bh, parameters) - val height = us.stateContext.currentHeight - val blockTx = validTransactionFromBoxes( - bh.boxes.take(2).values.toIndexedSeq, - outputsProposition = feeProp - ) - - val txs = - CandidateGenerator.collectFees(height, Seq(blockTx), defaultMinerPk, emptyStateContext).toSeq - val incorrect = CandidateGenerator - .collectFees(height, Seq(blockTx), proveDlogGen.sample.get, emptyStateContext) - .toSeq - txs.length shouldBe 1 - val feeTx = txs.head - feeTx.outputs.length shouldBe 1 - feeTx.outputs.head.value shouldBe txs.flatMap(_.outputs).map(_.value).sum - feeTx.outputs.head.propositionBytes shouldEqual expectedRewardOutputScriptBytes( - defaultMinerPk - ) - - us.applyModifier(validFullBlock(None, us, blockTx +: incorrect), None)(_ => ()) shouldBe 'failure - us.applyModifier(validFullBlock(None, us, blockTx +: txs), None)(_ => ()) shouldBe 'success - } - - property("filter out double spend txs") { - val tx = validErgoTransactionGen.sample.get._2 - CandidateGenerator.doublespend(Seq(tx), tx) shouldBe true - - val inputs = validErgoTransactionGenTemplate(minAssets = 0, maxAssets = -1).sample.get._1 - val (l, r) = inputs.splitAt(50) - val tx_1 = validTransactionFromBoxes(l) - val tx_2 = validTransactionFromBoxes(r :+ l.last) //conflicting with tx_1 - val tx_3 = validTransactionFromBoxes(r) //conflicting with tx_2, not conflicting with tx_1 - - CandidateGenerator.doublespend(Seq(tx_1), tx_2) shouldBe true - CandidateGenerator.doublespend(Seq(tx_1), tx_3) shouldBe false - CandidateGenerator.doublespend(Seq(tx_1, tx_2), tx_1) shouldBe true - CandidateGenerator.doublespend(Seq(tx_1, tx_2), tx_2) shouldBe true - CandidateGenerator.doublespend(Seq(tx_1, tx_3), tx) shouldBe false - } - - property("should only collect valid transactions") { - def checkCollectTxs( - maxCost: Int, - maxSize: Int, - withTokens: Boolean = false - ): Unit = { - - val bh = boxesHolderGen.sample.get - val rnd = new RandomWrapper - val us = createUtxoState(bh, parameters) - val inputs = bh.boxes.values.toIndexedSeq.takeRight(100) - val txsWithFees = inputs.map(i => - validTransactionFromBoxes(IndexedSeq(i), rnd, issueNew = withTokens, feeProp) - ) - val head = txsWithFees.head - - val h = validFullBlock(None, us, bh, rnd).header - val upcomingContext = us.stateContext.upcoming( - h.minerPk, - h.timestamp, - h.nBits, - h.votes, - emptyVSUpdate, - h.version - ) - upcomingContext.currentHeight shouldBe (us.stateContext.currentHeight + 1) - - val fromSmallMempool = CandidateGenerator - .collectTxs( - defaultMinerPk, - maxCost, - maxSize, - us, - upcomingContext, - Seq(head) - ) - ._1 - fromSmallMempool.size shouldBe 2 - fromSmallMempool.contains(head) shouldBe true - - val fromBigMempool = CandidateGenerator - .collectTxs( - defaultMinerPk, - maxCost, - maxSize, - us, - upcomingContext, - txsWithFees - ) - ._1 - - val newBoxes = fromBigMempool.flatMap(_.outputs) - val costs: Seq[Int] = fromBigMempool.map { tx => - us.validateWithCost(tx, upcomingContext, Int.MaxValue, Some(verifier)).getOrElse { - val boxesToSpend = - tx.inputs.map(i => newBoxes.find(b => b.id sameElements i.boxId).get) - tx.statefulValidity(boxesToSpend, IndexedSeq(), upcomingContext).get - } - } - - fromBigMempool.length should be > 2 - fromBigMempool.map(_.size).sum should be < maxSize - costs.sum should be < maxCost - if (!withTokens) fromBigMempool.size should be < txsWithFees.size - } - - // transactions reach computation cost block limit - checkCollectTxs(parameters.maxBlockCost, Int.MaxValue) - - // transactions reach block size limit - checkCollectTxs(Int.MaxValue, 4096) - - // miner collects correct transactions from mempool even if they have tokens - checkCollectTxs(Int.MaxValue, Int.MaxValue, withTokens = true) - - } - - property("should not be able to spend recent fee boxes") { - - val delta = 1 - val inputsNum = 2 - val feeProposition = ErgoTreePredef.feeProposition(delta) - - val bh = boxesHolderGen.sample.get - var us = createUtxoState(bh, parameters) - val height = ErgoHistory.EmptyHistoryHeight - - val ms = MonetarySettings(minerRewardDelay = delta) - val st = settings.copy(chainSettings = settings.chainSettings.copy(monetary = ms)) - val sc = ErgoStateContext.empty(genesisStateDigest, st, parameters) - val txBoxes = bh.boxes.grouped(inputsNum).map(_.values.toIndexedSeq).toSeq - - val blockTx = - validTransactionFromBoxes(txBoxes.head, outputsProposition = feeProposition) - val txs = CandidateGenerator - .collectFees(height, Seq(blockTx), defaultMinerPk, sc) - .toSeq - val block = validFullBlock(None, us, blockTx +: txs) - - us = us.applyModifier(block, None)(_ => ()).get - - val blockTx2 = - validTransactionFromBoxes(txBoxes(1), outputsProposition = feeProposition) - val block2 = validFullBlock(Some(block), us, IndexedSeq(blockTx2)) - - val earlySpendingTx = - validTransactionFromBoxes(txs.head.outputs, stateCtxOpt = Some(us.stateContext)) - - val invalidBlock2 = - validFullBlock(Some(block), us, IndexedSeq(earlySpendingTx, blockTx2)) - - us.applyModifier(invalidBlock2, None)(_ => ()) shouldBe 'failure - - us = us.applyModifier(block2, None)(_ => ()).get - - val earlySpendingTx2 = - validTransactionFromBoxes(txs.head.outputs, stateCtxOpt = Some(us.stateContext)) - - val blockTx3 = - validTransactionFromBoxes(txBoxes(2), outputsProposition = feeProposition) - val block3 = validFullBlock(Some(block2), us, IndexedSeq(earlySpendingTx2, blockTx3)) - - us.applyModifier(block3, None)(_ => ()) shouldBe 'success - } - - property("collect reward from both emission box and fees") { - val (us, _) = createUtxoState(settings) - us.emissionBoxOpt should not be None - val expectedReward = emission.minersRewardAtHeight(us.stateContext.currentHeight) - - forAll( - Gen.nonEmptyListOf(validErgoTransactionGenTemplate(minAssets = 0, propositionGen = feeProp)) - ) { btxs => - val blockTxs = btxs.map(_._2) - val height = ErgoHistory.EmptyHistoryHeight - val txs = CandidateGenerator.collectRewards( - us.emissionBoxOpt, - height, - blockTxs, - defaultMinerPk, - emptyStateContext - ) - txs.length shouldBe 2 - - val emissionTx = txs.head - emissionTx.outputs.length shouldBe 2 - emissionTx.outputs.last.value shouldBe expectedReward - emissionTx.outputs.last.propositionBytes shouldEqual expectedRewardOutputScriptBytes( - defaultMinerPk - ) - - val feeTx = txs.last - feeTx.outputs.length shouldBe 1 - feeTx.outputs.head.value shouldBe blockTxs.flatMap(_.outputs).map(_.value).sum - feeTx.outputs.head.propositionBytes shouldEqual expectedRewardOutputScriptBytes( - defaultMinerPk - ) - } - } - - property("it should calculate average block mining time from creation timestamps") { - val timestamps1 = System.currentTimeMillis() - val timestamps2 = timestamps1 + 100 - val timestamps3 = timestamps2 + 200 - val timestamps4 = timestamps3 + 300 - val avgMiningTime = { - CandidateGenerator.getBlockMiningTimeAvg( - Vector(timestamps1, timestamps2, timestamps3, timestamps4) - ) - } - avgMiningTime shouldBe 200.millis - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala deleted file mode 100644 index 148d5ebffb..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala +++ /dev/null @@ -1,258 +0,0 @@ -package org.ergoplatform.mining - -import akka.actor.{ActorRef, ActorSystem} -import akka.pattern.{StatusReply, ask} -import akka.testkit.{TestKit, TestProbe} -import akka.util.Timeout -import org.bouncycastle.util.BigIntegers -import org.ergoplatform.mining.CandidateGenerator.{Candidate, GenerateCandidate} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied -import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers} -import org.ergoplatform.nodeView.history.ErgoHistoryReader -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef} -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.ErgoTestHelpers -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} -import org.scalatest.concurrent.Eventually -import org.scalatest.flatspec.AnyFlatSpec -import sigmastate.crypto.DLogProtocol -import sigmastate.crypto.DLogProtocol.DLogProverInput - -import scala.concurrent.duration._ - -class CandidateGeneratorSpec extends AnyFlatSpec with ErgoTestHelpers with Eventually { - - implicit private val timeout: Timeout = defaultTimeout - - private val newBlockSignal: Class[FullBlockApplied] = classOf[FullBlockApplied] - private val newBlockDelay: FiniteDuration = 30.seconds - private val candidateGenDelay: FiniteDuration = 3.seconds - private val blockValidationDelay: FiniteDuration = 2.seconds - - val defaultSettings: ErgoSettings = { - val empty = ErgoSettings.read() - val nodeSettings = empty.nodeSettings.copy( - mining = true, - stateType = StateType.Utxo, - internalMinerPollingInterval = 1.second, - offlineGeneration = true, - verifyTransactions = true - ) - val chainSettings = empty.chainSettings.copy(blockInterval = 1.seconds) - empty.copy(nodeSettings = nodeSettings, chainSettings = chainSettings) - } - - it should "provider candidate to internal miner and verify and apply his solution" in new TestKit( - ActorSystem() - ) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - - val viewHolderRef: ActorRef = ErgoNodeViewRef(defaultSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(viewHolderRef) - - val candidateGenerator: ActorRef = - CandidateGenerator( - defaultMinerSecret.publicImage, - readersHolderRef, - viewHolderRef, - defaultSettings - ) - ErgoMiningThread(defaultSettings, candidateGenerator, defaultMinerSecret.w) - - // after applying solution from miner - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - system.terminate() - } - - it should "let multiple miners compete" in new TestKit(ActorSystem()) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - - val viewHolderRef: ActorRef = ErgoNodeViewRef(defaultSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(viewHolderRef) - - val candidateGenerator: ActorRef = - CandidateGenerator( - defaultMinerSecret.publicImage, - readersHolderRef, - viewHolderRef, - defaultSettings - ) - - val m1 = ErgoMiningThread(defaultSettings, candidateGenerator, defaultMinerSecret.w) - val m2 = ErgoMiningThread(defaultSettings, candidateGenerator, defaultMinerSecret.w) - val m3 = ErgoMiningThread(defaultSettings, candidateGenerator, defaultMinerSecret.w) - - // after applying solution from miner - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - m1.tell(ErgoMiningThread.GetSolvedBlocksCount, testProbe.ref) - - val m1Count = - testProbe.expectMsgClass(50.millis, classOf[ErgoMiningThread.SolvedBlocksCount]) - m2.tell(ErgoMiningThread.GetSolvedBlocksCount, testProbe.ref) - - val m2Count = - testProbe.expectMsgClass(50.millis, classOf[ErgoMiningThread.SolvedBlocksCount]) - m3.tell(ErgoMiningThread.GetSolvedBlocksCount, testProbe.ref) - - val m3Count = - testProbe.expectMsgClass(50.millis, classOf[ErgoMiningThread.SolvedBlocksCount]) - - List(m1Count, m2Count, m3Count).map(_.count).sum should be >= 3 - system.terminate() - } - - it should "cache candidate until newly mined block is applied" in new TestKit( - ActorSystem() - ) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - - val viewHolderRef: ActorRef = ErgoNodeViewRef(defaultSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(viewHolderRef) - - val candidateGenerator: ActorRef = - CandidateGenerator( - defaultMinerSecret.publicImage, - readersHolderRef, - viewHolderRef, - defaultSettings - ) - - expectNoMessage(1.second) - candidateGenerator.tell(GenerateCandidate(Seq.empty, reply = true), testProbe.ref) - - val block = testProbe.expectMsgPF(candidateGenDelay) { - case StatusReply.Success(candidate: Candidate) => - defaultSettings.chainSettings.powScheme - .proveCandidate(candidate.candidateBlock, defaultMinerSecret.w, 0, 1000) - .get - } - - // now block should be cached - (0 to 20).foreach { _ => - candidateGenerator.tell(GenerateCandidate(Seq.empty, reply = true), testProbe.ref) - testProbe.expectMsgClass(5.millis, classOf[StatusReply[_]]) - } - - candidateGenerator.tell(block.header.powSolution, testProbe.ref) - testProbe.expectMsg(blockValidationDelay, StatusReply.success(())) - // after applying solution - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - system.terminate() - } - - it should "pool transactions should be removed from pool when block is mined" in new TestKit( - ActorSystem() - ) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - val viewHolderRef: ActorRef = ErgoNodeViewRef(defaultSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(viewHolderRef) - - val candidateGenerator: ActorRef = - CandidateGenerator( - defaultMinerSecret.publicImage, - readersHolderRef, - viewHolderRef, - defaultSettings - ) - - val readers: Readers = await((readersHolderRef ? GetReaders).mapTo[Readers]) - - val history: ErgoHistoryReader = readers.h - val startBlock: Option[Header] = history.bestHeaderOpt - - // generate block to use reward as our tx input - candidateGenerator.tell(GenerateCandidate(Seq.empty, reply = true), testProbe.ref) - testProbe.expectMsgPF(candidateGenDelay) { - case StatusReply.Success(candidate: Candidate) => - val block = defaultSettings.chainSettings.powScheme - .proveCandidate(candidate.candidateBlock, defaultMinerSecret.w, 0, 1000) - .get - // let's pretend we are mining at least a bit so it is realistic - expectNoMessage(200.millis) - candidateGenerator.tell(block.header.powSolution, testProbe.ref) - - // we fish either for ack or SSM as the order is non-deterministic - testProbe.fishForMessage(blockValidationDelay) { - case StatusReply.Success(()) => - testProbe.expectMsgPF(candidateGenDelay) { - case FullBlockApplied(header) if header.id != block.header.parentId => - } - true - case FullBlockApplied(header) if header.id != block.header.parentId => - testProbe.expectMsg(StatusReply.Success(())) - true - } - } - - // build new transaction that uses miner's reward as input - val prop: DLogProtocol.ProveDlog = - DLogProverInput(BigIntegers.fromUnsignedByteArray("test".getBytes())).publicImage - val newlyMinedBlock = readers.h.bestFullBlockOpt.get - val rewardBox: ErgoBox = newlyMinedBlock.transactions.last.outputs.last - rewardBox.propositionBytes shouldBe ErgoTreePredef - .rewardOutputScript(emission.settings.minerRewardDelay, defaultMinerPk) - .bytes - val input = Input(rewardBox.id, emptyProverResult) - - val outputs = IndexedSeq( - new ErgoBoxCandidate(rewardBox.value, prop, readers.s.stateContext.currentHeight) - ) - val unsignedTx = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs) - - val tx = ErgoTransaction( - defaultProver - .sign(unsignedTx, IndexedSeq(rewardBox), IndexedSeq(), readers.s.stateContext) - .get - ) - - testProbe.expectNoMessage(200.millis) - // mine a block with that transaction - candidateGenerator.tell(GenerateCandidate(Seq(tx), reply = true), testProbe.ref) - testProbe.expectMsgPF(candidateGenDelay) { - case StatusReply.Success(candidate: Candidate) => - val block = defaultSettings.chainSettings.powScheme - .proveCandidate(candidate.candidateBlock, defaultMinerSecret.w, 0, 1000) - .get - testProbe.expectNoMessage(200.millis) - candidateGenerator.tell(block.header.powSolution, testProbe.ref) - - // we fish either for ack or SSM as the order is non-deterministic - testProbe.fishForMessage(blockValidationDelay) { - case StatusReply.Success(()) => - testProbe.expectMsgPF(candidateGenDelay) { - case FullBlockApplied(header) if header.id != block.header.parentId => - } - true - case FullBlockApplied(header) if header.id != block.header.parentId => - testProbe.expectMsg(StatusReply.Success(())) - true - } - } - - // new transaction should be cleared from pool after applying new block - await((readersHolderRef ? GetReaders).mapTo[Readers]).m.size shouldBe 0 - - // validate total amount of transactions created - val blocks: IndexedSeq[ErgoFullBlock] = readers.h - .chainToHeader(startBlock, readers.h.bestHeaderOpt.get) - ._2 - .headers - .flatMap(readers.h.getFullBlock) - val txs: Seq[ErgoTransaction] = blocks.flatMap(_.blockTransactions.transactions) - txs should have length 3 // 2 rewards and one regular tx - system.terminate() - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala deleted file mode 100644 index 25258277e3..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala +++ /dev/null @@ -1,432 +0,0 @@ -package org.ergoplatform.mining - -import akka.actor.{ActorRef, ActorSystem} -import akka.pattern.{StatusReply, ask} -import akka.testkit.{TestKit, TestProbe} -import akka.util.Timeout -import org.bouncycastle.util.BigIntegers -import org.ergoplatform.mining.CandidateGenerator.{Candidate, GenerateCandidate} -import org.ergoplatform.mining.ErgoMiner.StartMining -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction, UnsignedErgoTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction -import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers} -import org.ergoplatform.nodeView.history.ErgoHistoryReader -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.nodeView.wallet._ -import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef} -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.ErgoTestHelpers -import org.ergoplatform.utils.generators.ValidBlocksGenerators -import org.ergoplatform.wallet.interpreter.ErgoInterpreter -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} -import org.scalatest.concurrent.Eventually -import org.scalatest.flatspec.AnyFlatSpec -import sigmastate.SigmaAnd -import sigmastate.Values.{ErgoTree, SigmaPropConstant} -import sigmastate.crypto.DLogProtocol -import sigmastate.crypto.DLogProtocol.DLogProverInput - -import scala.annotation.tailrec -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.duration._ -import scala.language.postfixOps - -class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGenerators with Eventually { - - implicit private val timeout: Timeout = defaultTimeout - - private val newBlockSignal: Class[FullBlockApplied] = classOf[FullBlockApplied] - private val newBlockDelay: FiniteDuration = 30 seconds - private val candidateGenDelay: FiniteDuration = 3.seconds - private val blockValidationDelay: FiniteDuration = 2.seconds - - private def getWorkMessage(minerRef: ActorRef, mandatoryTransactions: Seq[ErgoTransaction]): WorkMessage = - await(minerRef.askWithStatus(GenerateCandidate(mandatoryTransactions, reply = true)).mapTo[Candidate].map(_.externalVersion)) - - val defaultSettings: ErgoSettings = { - val empty = ErgoSettings.read() - - val nodeSettings = empty.nodeSettings.copy(mining = true, - stateType = StateType.Utxo, - internalMinerPollingInterval = 2.second, - maxTransactionCost = 100000, - offlineGeneration = true, - verifyTransactions = true) - val chainSettings = empty.chainSettings.copy(blockInterval = 2.seconds) - empty.copy(nodeSettings = nodeSettings, chainSettings = chainSettings) - } - - it should "not include too costly transactions" in new TestKit(ActorSystem()) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - val complexScript: ErgoTree = (0 until 100).foldLeft(SigmaAnd(SigmaPropConstant(defaultMinerPk), SigmaPropConstant(defaultMinerPk))) { (l, _) => - SigmaAnd(SigmaPropConstant(defaultMinerPk), l) - } - complexScript.complexity shouldBe 28077 - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - - val minerRef: ActorRef = ErgoMiner( - ergoSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - expectNoMessage(1 second) - val r: Readers = await((readersHolderRef ? GetReaders).mapTo[Readers]) - - minerRef ! StartMining - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - val boxToSpend: ErgoBox = r.h.bestFullBlockOpt.get.transactions.last.outputs.last - boxToSpend.propositionBytes shouldBe ErgoTreePredef.rewardOutputScript(emission.settings.minerRewardDelay, defaultMinerPk).bytes - - val input = Input(boxToSpend.id, emptyProverResult) - - // create transaction with output with costly proposition - val output = new ErgoBoxCandidate(boxToSpend.value / 10, complexScript, r.s.stateContext.currentHeight) - val outputs = (0 until 10).map(_ => output) - val unsignedTx = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs) - val tx = defaultProver.sign(unsignedTx, IndexedSeq(boxToSpend), IndexedSeq(), r.s.stateContext).get - nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(ErgoTransaction(tx), None)) - expectNoMessage(1 seconds) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - await((readersHolderRef ? GetReaders).mapTo[Readers]).m.size shouldBe 0 - - //check that tx is included into UTXO set - val state = await((readersHolderRef ? GetReaders).mapTo[Readers]).s.asInstanceOf[UtxoState] - tx.outputs.foreach(o => state.boxById(o.id).get shouldBe o) - - // try to spend all the boxes with complex scripts - val costlyInputs = tx.outputs.map(o => Input(o.id, emptyProverResult)) - val costlyOut = new ErgoBoxCandidate(tx.outputs.map(_.value).sum, complexScript, r.s.stateContext.currentHeight) - val unsignedComplexTx = new UnsignedErgoTransaction(costlyInputs, IndexedSeq(), IndexedSeq(costlyOut)) - val costlyTx = defaultProver.sign(unsignedComplexTx, tx.outputs, IndexedSeq(), r.s.stateContext).get - - val txCost = - state.validateWithCost( - ErgoTransaction(costlyTx.inputs, costlyTx.dataInputs, costlyTx.outputCandidates), - r.s.stateContext, - costLimit = 440000, - None - ).get - txCost shouldBe 439080 - - // send costly transaction to the mempool - nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(ErgoTransaction(costlyTx), None)) - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - // costly tx was removed from mempool - expectNoMessage(1 second) - await((readersHolderRef ? GetReaders).mapTo[Readers]).m.size shouldBe 0 - // costly tx was not included - val state2 = await((readersHolderRef ? GetReaders).mapTo[Readers]).s.asInstanceOf[UtxoState] - tx.outputs.foreach(o => state2.boxById(o.id) should not be None) - costlyTx.outputs.foreach(o => state2.boxById(o.id) shouldBe None) - } - - it should "not freeze while mempool is full" in new TestKit(ActorSystem()) { - // generate amount of transactions, twice more than can fit in one block - val desiredSize: Int = Math.ceil((parameters.maxBlockCost / ErgoInterpreter.interpreterInitCost) * 1.2).toInt - val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - expectNoMessage(1 second) - val r: Readers = requestReaders - val wallet: ErgoWalletReader = r.w - - val minerRef: ActorRef = ErgoMiner( - ergoSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - minerRef ! StartMining - - // wait for 1 block to be generated - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - @tailrec - def loop(toSend: Int): Unit = { - val toSpend: Seq[ErgoBox] = await( - wallet.walletBoxes(unspentOnly = false, considerUnconfirmed = false) - ).map(_.trackedBox.box).toList - log.debug(s"Generate more transactions from ${toSpend.length} boxes. $toSend remains," + - s"pool size: ${requestReaders.m.size}") - val txs: Seq[ErgoTransaction] = toSpend.take(toSend) map { boxToSend => - val inputs = IndexedSeq(Input(boxToSend.id, emptyProverResult)) - - val feeBox = new ErgoBoxCandidate(boxToSend.value / desiredSize, feeProp, r.s.stateContext.currentHeight) - val outputs = (1 until desiredSize).map { _ => - new ErgoBoxCandidate(boxToSend.value / desiredSize, defaultMinerPk, r.s.stateContext.currentHeight) - } - val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), feeBox +: outputs) - ErgoTransaction( - defaultProver.sign( - unsignedTx, - IndexedSeq(boxToSend), - IndexedSeq(), - r.s.stateContext - ).get - ) - } - - txs.map(tx => UnconfirmedTransaction(tx, None)).foreach(nodeViewHolderRef ! LocallyGeneratedTransaction(_)) - - if (toSend > toSpend.size) { - // wait for the next block - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - loop(toSend - toSpend.size) - } - } - - def requestReaders: Readers = await((readersHolderRef ? GetReaders).mapTo[Readers]) - - // Generate and send `desiredSize` transactions to mempool - loop(desiredSize) - - implicit val patienceConfig: PatienceConfig = PatienceConfig(10.second, 100.millis) - eventually { - requestReaders.m.size should be > 10 - } - - // wait for mempool to be cleaned - scorex.core.utils.untilTimeout(5.minute, 500.millis) { - log.debug(s"Wait until transactions in mempool will be included into blocks. Currents size: ${requestReaders.m.size}") - requestReaders.m.size shouldBe 0 - system.terminate() - } - } - - it should "include only one transaction from 2 spending the same box" in new TestKit(ActorSystem()) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - - val minerRef: ActorRef = ErgoMiner( - ergoSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - expectNoMessage(1 second) - val r: Readers = await((readersHolderRef ? GetReaders).mapTo[Readers]) - - val history: ErgoHistoryReader = r.h - val startBlock: Option[Header] = history.bestHeaderOpt - - minerRef ! StartMining - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - val prop1: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage - val prop2: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage - - val boxToDoubleSpend: ErgoBox = r.h.bestFullBlockOpt.get.transactions.last.outputs.last - boxToDoubleSpend.propositionBytes shouldBe ErgoTreePredef.rewardOutputScript(emission.settings.minerRewardDelay, defaultMinerPk).bytes - - val input = Input(boxToDoubleSpend.id, emptyProverResult) - - val outputs1 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, prop1, r.s.stateContext.currentHeight)) - val unsignedTx1 = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs1) - val tx1 = defaultProver.sign(unsignedTx1, IndexedSeq(boxToDoubleSpend), IndexedSeq(), r.s.stateContext).get - val outputs2 = IndexedSeq(new ErgoBoxCandidate(boxToDoubleSpend.value, prop2, r.s.stateContext.currentHeight)) - val unsignedTx2 = new UnsignedErgoTransaction(IndexedSeq(input), IndexedSeq(), outputs2) - val tx2 = ErgoTransaction(defaultProver.sign(unsignedTx2, IndexedSeq(boxToDoubleSpend), IndexedSeq(), r.s.stateContext).get) - - // As double-spending transactions are filtered out in the mempool, the only way to push them is to order to - // include double-spending transaction directly via mandatoryTransactions argument of PrepareCandidate command - nodeViewHolderRef ! LocallyGeneratedTransaction(UnconfirmedTransaction(ErgoTransaction(tx1), None)) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - testProbe.expectNoMessage(200.millis) - minerRef.tell(GenerateCandidate(Seq(tx2), reply = true), testProbe.ref) - testProbe.expectMsgPF(candidateGenDelay) { - case StatusReply.Success(candidate: Candidate) => - val block = defaultSettings.chainSettings.powScheme - .proveCandidate(candidate.candidateBlock, defaultMinerSecret.w, 0, 1000) - .get - testProbe.expectNoMessage(200.millis) - minerRef.tell(block.header.powSolution, testProbe.ref) - - // we fish either for ack or SSM as the order is non-deterministic - testProbe.fishForMessage(blockValidationDelay) { - case StatusReply.Success(()) => - testProbe.expectMsgPF(candidateGenDelay) { - case FullBlockApplied(header) if header.id != block.header.parentId => - } - true - case FullBlockApplied(header) if header.id != block.header.parentId => - testProbe.expectMsg(StatusReply.Success(())) - true - } - } - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - await((readersHolderRef ? GetReaders).mapTo[Readers]).m.size shouldBe 0 - - val blocks: IndexedSeq[ErgoFullBlock] = r.h.chainToHeader(startBlock, r.h.bestHeaderOpt.get)._2.headers.flatMap(r.h.getFullBlock) - val txs: Seq[ErgoTransaction] = blocks.flatMap(_.blockTransactions.transactions) - //Make sure that only tx got into chain - txs.filter(tx => tx.id == tx1.id || tx.id == tx2.id) should have length 1 - system.terminate() - } - - it should "prepare external candidate" in new TestKit(ActorSystem()) { - val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - - def minerRef: ActorRef = ErgoMiner( - ergoSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - - val passiveMiner: ActorRef = minerRef - passiveMiner ! StartMining - - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 200.millis) // it takes a while before PK is set - eventually(await(passiveMiner.askWithStatus(GenerateCandidate(Seq.empty, reply = true)).mapTo[Candidate])) - system.terminate() - } - - it should "include mandatory transactions" in new TestKit(ActorSystem()) { - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - val ergoSettings: ErgoSettings = defaultSettings.copy(directory = createTempDir.getAbsolutePath) - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(ergoSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - - val minerRef: ActorRef = ErgoMiner( - ergoSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - expectNoMessage(1 second) - val r: Readers = await((readersHolderRef ? GetReaders).mapTo[Readers]) - - minerRef ! StartMining - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - val prop1: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test1".getBytes())).publicImage - val prop2: DLogProtocol.ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray("test2".getBytes())).publicImage - - val mBox: ErgoBox = r.h.bestFullBlockOpt.get.transactions.last.outputs.last - val mInput = Input(mBox.id, emptyProverResult) - - val outputs1 = IndexedSeq(new ErgoBoxCandidate(mBox.value, prop1, r.s.stateContext.currentHeight)) - val unsignedTx1 = new UnsignedErgoTransaction(IndexedSeq(mInput), IndexedSeq(), outputs1) - val mandatoryTxLike1 = defaultProver.sign(unsignedTx1, IndexedSeq(mBox), IndexedSeq(), r.s.stateContext).get - val mandatoryTx1 = ErgoTransaction(mandatoryTxLike1) - - val outputs2 = IndexedSeq(new ErgoBoxCandidate(mBox.value, prop2, r.s.stateContext.currentHeight)) - val unsignedTx2 = new UnsignedErgoTransaction(IndexedSeq(mInput), IndexedSeq(), outputs2) - val mandatoryTxLike2 = defaultProver.sign(unsignedTx2, IndexedSeq(mBox), IndexedSeq(), r.s.stateContext).get - val mandatoryTx2 = ErgoTransaction(mandatoryTxLike2) - mandatoryTx1.bytes.sameElements(mandatoryTx2.bytes) shouldBe false - - val ecb = getWorkMessage(minerRef, Seq.empty) - ecb.proofsForMandatoryTransactions.isDefined shouldBe false - - val ecb1 = getWorkMessage(minerRef, Seq(mandatoryTx1)) - ecb1.proofsForMandatoryTransactions.get.txProofs.length shouldBe 1 - ecb1.proofsForMandatoryTransactions.get.check() shouldBe true - - val ecb2 = getWorkMessage(minerRef, Seq(mandatoryTx2)) - ecb2.msg.sameElements(ecb1.msg) shouldBe false - ecb2.proofsForMandatoryTransactions.get.txProofs.length shouldBe 1 - ecb2.proofsForMandatoryTransactions.get.check() shouldBe true - - val ecb3 = getWorkMessage(minerRef, Seq.empty) - ecb3.msg.sameElements(ecb2.msg) shouldBe true - ecb3.proofsForMandatoryTransactions.get.txProofs.length shouldBe 1 - ecb3.proofsForMandatoryTransactions.get.check() shouldBe true - - system.terminate() - } - - it should "mine after HF" in new TestKit(ActorSystem()) { - val forkHeight = 3 - - val testProbe = new TestProbe(system) - system.eventStream.subscribe(testProbe.ref, newBlockSignal) - - val forkSettings: ErgoSettings = { - val empty = ErgoSettings.read() - - val nodeSettings = empty.nodeSettings.copy(mining = true, - stateType = StateType.Utxo, - internalMinerPollingInterval = 2.second, - offlineGeneration = true, - verifyTransactions = true) - val chainSettings = empty.chainSettings.copy( - blockInterval = 2.seconds, - epochLength = forkHeight, - voting = empty.chainSettings.voting.copy( - version2ActivationHeight = forkHeight, - version2ActivationDifficultyHex = "10", - votingLength = forkHeight) - ) - empty.copy(nodeSettings = nodeSettings, chainSettings = chainSettings, directory = createTempDir.getAbsolutePath) - } - - val nodeViewHolderRef: ActorRef = ErgoNodeViewRef(forkSettings) - val readersHolderRef: ActorRef = ErgoReadersHolderRef(nodeViewHolderRef) - - val minerRef: ActorRef = ErgoMiner( - forkSettings, - nodeViewHolderRef, - readersHolderRef, - Some(defaultMinerSecret) - ) - - minerRef ! StartMining - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - val wm1 = getWorkMessage(minerRef, Seq.empty) - (wm1.h.get >= forkHeight) shouldBe true - - testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - implicit val patienceConfig: PatienceConfig = PatienceConfig(1.seconds, 50.millis) - eventually { - val wm2 = getWorkMessage(minerRef, Seq.empty) - (wm2.h.get >= forkHeight) shouldBe true - wm1.msg.sameElements(wm2.msg) shouldBe false - - val v2Block = testProbe.expectMsgClass(newBlockDelay, newBlockSignal) - - val h2 = v2Block.header - h2.version shouldBe 2 - h2.minerPk shouldBe defaultMinerPk.value - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustmentSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustmentSpecification.scala deleted file mode 100644 index 6c7d6528bd..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultyAdjustmentSpecification.scala +++ /dev/null @@ -1,190 +0,0 @@ -package org.ergoplatform.mining.difficulty - -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.settings.ChainSettings -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.{Arbitrary, Gen} - -import scala.concurrent.duration._ -import scala.util.Try - -class DifficultyAdjustmentSpecification extends ErgoPropertyTest { - - val precision = 0.0001 - val minDiff: BigInt = (BigDecimal(1) / precision).toBigInt() - val Epoch = 123 - - val UseLastEpochs = 4 - val DesiredInterval: FiniteDuration = 1.minute - - def chainSettings(blockInterval: FiniteDuration = DesiredInterval, - useLastEpochs: Int = UseLastEpochs, - epochLength: Int = Epoch): ChainSettings = - settings.chainSettings.copy(blockInterval = blockInterval, useLastEpochs = useLastEpochs, epochLength = epochLength) - - val control = new DifficultyAdjustment(chainSettings()) - - property("nextRecalculationHeight vectors") { - val epochLength = 128 - control.nextRecalculationHeight(926976, epochLength) shouldBe 926977 - control.nextRecalculationHeight(926977, epochLength) shouldBe 927105 - control.nextRecalculationHeight(926975, epochLength) shouldBe 926977 - control.nextRecalculationHeight(926950, epochLength) shouldBe 926977 - control.nextRecalculationHeight(1, epochLength) shouldBe 129 - control.nextRecalculationHeight(129, epochLength) shouldBe 257 - control.nextRecalculationHeight(256, epochLength) shouldBe 257 - } - - property("heightsForNextRecalculation vectors") { - val epochLength = 128 - control.heightsForNextRecalculation(926976, epochLength) shouldBe Seq(926464, 926592, 926720, 926848, 926976) - control.heightsForNextRecalculation(926977, epochLength) shouldBe Seq(926592, 926720, 926848, 926976, 927104) - control.heightsForNextRecalculation(926975, epochLength) shouldBe Seq(926464, 926592, 926720, 926848, 926976) - control.heightsForNextRecalculation(926950, epochLength) shouldBe Seq(926464, 926592, 926720, 926848, 926976) - control.heightsForNextRecalculation(1, epochLength) shouldBe Seq(0, 128) - control.heightsForNextRecalculation(129, epochLength) shouldBe Seq(0, 128, 256) - control.heightsForNextRecalculation(256, epochLength) shouldBe Seq(0, 128, 256) - } - - property("previousHeadersRequiredForRecalculation() should return correct heights required for recalculation") { - val height = Epoch * (UseLastEpochs + 1) + 1 - control.previousHeightsRequiredForRecalculation(height, Epoch) shouldEqual - Seq(height - 4 * Epoch - 1, height - 3 * Epoch - 1, height - 2 * Epoch - 1, height - Epoch - 1, height - 1) - } - - property("previousHeadersRequiredForRecalculation() with Epoch = 1") { - forAll(Gen.choose(2, 1000)) { _ => - val useLastEpochs = 3 - val epochLength = 1 - val control = new DifficultyAdjustment(chainSettings(1.minute, useLastEpochs, epochLength)) - val height = useLastEpochs + 1 - control.previousHeightsRequiredForRecalculation(height, epochLength) shouldEqual (0 until height) - } - } - - property("previousHeadersRequiredForRecalculation() should return previous block if there should not be difficulty recalculation") { - control.previousHeightsRequiredForRecalculation(Epoch / 2 + 1, Epoch) shouldBe Seq(Epoch / 2) - control.previousHeightsRequiredForRecalculation(Epoch * UseLastEpochs, Epoch) shouldBe Seq(Epoch * UseLastEpochs - 1) - control.previousHeightsRequiredForRecalculation(Epoch * UseLastEpochs + 2, Epoch) shouldBe Seq(Epoch * UseLastEpochs + 1) - } - - property("previousHeadersRequiredForRecalculation() should return as much block heights as possible") { - control.previousHeightsRequiredForRecalculation(Epoch + 1, Epoch) shouldBe Seq(0, Epoch) - control.previousHeightsRequiredForRecalculation(2 * Epoch + 1, Epoch) shouldBe Seq(0, Epoch, 2 * Epoch) - control.previousHeightsRequiredForRecalculation(3 * Epoch + 1, Epoch) shouldBe Seq(0, Epoch, 2 * Epoch, 3 * Epoch) - control.previousHeightsRequiredForRecalculation(4 * Epoch + 1, Epoch) shouldBe Seq(0, Epoch, 2 * Epoch, 3 * Epoch, 4 * Epoch) - control.previousHeightsRequiredForRecalculation(5 * Epoch + 1, Epoch) shouldBe Seq(Epoch, 2 * Epoch, 3 * Epoch, 4 * Epoch, 5 * Epoch) - } - - property("previousHeadersRequiredForRecalculation() should generate valid heights for calculate()") { - forAll(Gen.choose(1, Int.MaxValue), defaultHeaderGen) { (height: Int, header: Header) => - val previousHeaders = control.previousHeightsRequiredForRecalculation(height, Epoch) - .map(i => header.copy(timestamp = header.timestamp + i, height = i)) - - Try(control.calculate(previousHeaders, Epoch)) shouldBe 'success - } - } - - - property("calculate() should require correct heights") { - forAll(Gen.choose(UseLastEpochs, 10 * UseLastEpochs), defaultHeaderGen) { (i: Int, header: Header) => - val previousHeaders = control.previousHeightsRequiredForRecalculation(i * Epoch + 1, Epoch) - .map(i => header.copy(timestamp = header.timestamp + i, height = i)) - previousHeaders.length shouldBe UseLastEpochs + 1 - - Try(control.calculate(previousHeaders, Epoch)) shouldBe 'success - Try(control.calculate(previousHeaders.map(h => h.copy(height = h.height * 2)), Epoch)) shouldBe 'failure - } - } - - property("calculate() should decrease difficulty if block time interval is higher than expected") { - forAll(Gen.choose(UseLastEpochs, 10 * UseLastEpochs), defaultHeaderGen) { (startEpoch: Int, header: Header) => - whenever(header.requiredDifficulty > 10) { - val previousHeaders = control.previousHeightsRequiredForRecalculation(startEpoch * Epoch + 1, Epoch) - .map(i => header.copy(timestamp = header.timestamp + DesiredInterval.toMillis * 2 * i, height = i)) - previousHeaders.length shouldBe UseLastEpochs + 1 - - control.calculate(previousHeaders, Epoch) < header.requiredDifficulty shouldBe true - } - } - } - - - property("interpolate() vectors") { - val diff = BigInt("675204474840679645414180963439886534428") - control.interpolate(Seq((799167010, diff), (799167133, diff), (799167256, diff), (799167379, diff)), Epoch) shouldBe diff - - control.interpolate(Seq((123, diff), (246, diff), (369, diff), (492, diff)), Epoch) shouldBe diff - - control.interpolate(Vector((123, diff), (246, diff * 2), (369, diff * 2), (492, diff)), Epoch) shouldBe (diff * 3 / 2) - - control.interpolate(Vector((123, diff), (246, diff * 2), (369, diff * 3), (492, diff * 4)), Epoch) shouldBe BigInt("3376022374203398227070904817199432672139") - - } - - property("interpolate() for constant hashrate") { - forAll(epochGen, diffGen) { (startEpoch: Int, diff: BigInt) => - val previousDifficulties = (startEpoch * Epoch until (UseLastEpochs + startEpoch) * Epoch by Epoch).map(i => (i, diff)) - val newDiff = control.interpolate(previousDifficulties, Epoch) - (BigDecimal(newDiff - diff) / BigDecimal(diff)).toDouble should be < precision - } - } - - - property("interpolate() for linear hashrate growth") { - forAll(epochGen, diffGen, smallPositiveInt, smallPositiveInt) { (startEpoch, diff, epoch, useLastEpochs) => - whenever(useLastEpochs > 1) { - val control = new DifficultyAdjustment(chainSettings(1.minute, useLastEpochs, epoch)) - val previousDifficulties = (startEpoch * epoch until (useLastEpochs + startEpoch) * epoch by epoch).map(i => (i, diff * i)) - val newDiff = control.interpolate(previousDifficulties, epoch) - val expected = previousDifficulties.map(_._2).max + diff - equalsWithPrecision(expected, newDiff) - } - } - } - - property("calculate() for different epoch lengths and constant hashrate") { - forAll(defaultHeaderGen, smallPositiveInt, smallPositiveInt, Gen.choose(1, 60 * 60 * 1000)) { (header: Header, epoch, useLastEpochs, interval) => - whenever(useLastEpochs > 1 && header.requiredDifficulty >= 1) { - val control = new DifficultyAdjustment(chainSettings(interval.millis, useLastEpochs, epoch)) - val previousHeaders = control.previousHeightsRequiredForRecalculation(epoch * useLastEpochs + 1, epoch) - .map(i => header.copy(timestamp = header.timestamp + i * interval, height = i)) - previousHeaders.length shouldBe useLastEpochs + 1 - control.calculate(previousHeaders, epoch) shouldBe header.requiredDifficulty - } - } - } - - property("calculate() for different epoch lengths and linear hashrate") { - val step = 1000 - forAll(defaultHeaderGen, smallPositiveInt, smallPositiveInt, Gen.choose(1, 60 * 60 * 1000)) { (header: Header, epoch, useLastEpochs, interval) => - whenever(useLastEpochs > 1) { - val control = new DifficultyAdjustment(chainSettings(interval.millis, useLastEpochs, epoch)) - val previousHeaders = control.previousHeightsRequiredForRecalculation(epoch * useLastEpochs + 1, epoch).map { i => - header.copy(timestamp = header.timestamp + i * interval, - height = i, - nBits = DifficultySerializer.encodeCompactBits(DifficultySerializer.decodeCompactBits(header.nBits) + step)) - } - - previousHeaders.length shouldBe useLastEpochs + 1 - val expectedDifficulty = previousHeaders.last.requiredDifficulty + step - val error = BigDecimal(control.calculate(previousHeaders, epoch) - expectedDifficulty) / BigDecimal(expectedDifficulty) - error should be < BigDecimal(1) / DifficultyAdjustment.PrecisionConstant - } - } - } - - def equalsWithPrecision(i: BigInt, j: BigInt): Unit = { - require((BigDecimal(i - j) / BigDecimal(j)).toDouble < precision, s"$i and $j are too different") - } - - def diffGen: Gen[BigInt] = for { - rnd <- Arbitrary.arbitrary[BigInt] - diff = if (rnd < 0) -rnd + minDiff else rnd + minDiff - _ = assert(diff > 0, s"$diff,$minDiff,$rnd") - } yield diff - - - def epochGen: Gen[Int] = Gen.choose(1, Int.MaxValue - UseLastEpochs) - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultySerializerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultySerializerSpecification.scala deleted file mode 100644 index 2039994171..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/mining/difficulty/DifficultySerializerSpecification.scala +++ /dev/null @@ -1,31 +0,0 @@ -package org.ergoplatform.mining.difficulty - -import org.ergoplatform.utils.ErgoPropertyTest - -class DifficultySerializerSpecification extends ErgoPropertyTest { - - property("external vectors from BitcoinJ") { - val longs = Seq(0x180130e0, 0x18019eaf, 0x1802cc47, 0x1806f0a8, 0x187c3053, 0x1a05db8b, 0x1b0404cb, 0x1c20bca7, 0x1d00ffff, 0x181bc330, - 0x207fffff, 0x01003456, 0x01123456, 0x02008000, 0x05009234, 0x04923456, 0x04123456) - val expected = Seq("130e0000000000000000000000000000000000000000000", - "19eaf000000000000000000000000000000000000000000", - "2cc47000000000000000000000000000000000000000000", - "6f0a8000000000000000000000000000000000000000000", - "7c3053000000000000000000000000000000000000000000", - "5db8b0000000000000000000000000000000000000000000000", - "404cb000000000000000000000000000000000000000000000000", - "20bca700000000000000000000000000000000000000000000000000", - "ffff0000000000000000000000000000000000000000000000000000", - "1bc330000000000000000000000000000000000000000000", - "7fffff0000000000000000000000000000000000000000000000000000000000", - "0", - "12", - "80", - "92340000", - "-12345600", - "12345600") - val calculated: Seq[String] = longs.map(nBits => DifficultySerializer.decodeCompactBits(nBits).toString(16)) - - calculated shouldEqual expected - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/AdProofSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/AdProofSpec.scala deleted file mode 100644 index ffb09082d2..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/AdProofSpec.scala +++ /dev/null @@ -1,116 +0,0 @@ -package org.ergoplatform.modifiers.history - -import org.ergoplatform.ErgoBox -import org.ergoplatform.modifiers.state.StateChanges -import org.ergoplatform.settings.Algos.HF -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.Gen -import scorex.crypto.authds._ -import scorex.crypto.authds.avltree.batch.{BatchAVLProver, Insert} -import scorex.crypto.hash.Digest32 -import scorex.util._ -import sigmastate.helpers.TestingHelpers._ - - -class AdProofSpec extends ErgoPropertyTest { - val KL = 32 - - type Digest = ADDigest - type Proof = SerializedAdProof - - type PrevDigest = Digest - type NewDigest = Digest - - val emptyModifierId: ModifierId = bytesToId(Array.fill(32)(0.toByte)) - - private def insert(box: ErgoBox) = Insert(box.id, ADValue @@ box.bytes) - - private def createEnv(howMany: Int = 10): - (IndexedSeq[Insert], PrevDigest, NewDigest, Proof) = { - - val prover = new BatchAVLProver[Digest32, HF](KL, None) - val zeroBox = testBox(0, Constants.TrueLeaf, startHeight, Seq(), Map(), Array.fill(32)(0: Byte).toModifierId) - prover.performOneOperation(Insert(zeroBox.id, ADValue @@ zeroBox.bytes)) - prover.generateProof() - - val prevDigest = prover.digest - val boxes = (1 to howMany) map { i => testBox(1, Constants.TrueLeaf, startHeight, boxIndex = i.toShort) } - boxes.foreach(box => prover.performOneOperation(Insert(box.id, ADValue @@ box.bytes))) - val pf = prover.generateProof() - - val newDigest = prover.digest - val operations: IndexedSeq[Insert] = boxes.map(box => Insert(box.id, ADValue @@ box.bytes)) - (operations, prevDigest, newDigest, pf) - } - - property("verify should be success in simple case") { - forAll(Gen.choose(0, 1000)) { s => - whenever(s >= 0) { - val (operations, prevDigest, newDigest, pf) = createEnv(s) - val proof = ADProofs(emptyModifierId, pf) - proof.verify(StateChanges(IndexedSeq.empty, operations, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'success - } - } - } - - property("verify should be failed if first operation is missed") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, pf) - proof.verify(StateChanges(IndexedSeq.empty, operations.tail, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if last operation is missed") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, pf) - proof.verify(StateChanges(IndexedSeq.empty, operations.init, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if there are more operations than expected") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, pf) - val moreInsertions = operations :+ insert(testBox(10, Constants.TrueLeaf, creationHeight = startHeight)) - proof.verify(StateChanges(IndexedSeq.empty, moreInsertions, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if there are illegal operation") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, pf) - val differentInsertions = operations.init :+ insert(testBox(10, Constants.TrueLeaf, creationHeight = startHeight)) - proof.verify(StateChanges(IndexedSeq.empty, differentInsertions, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if there are operations in different order") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, pf) - val operationsInDifferentOrder = operations.last +: operations.init - proof.verify(StateChanges(IndexedSeq.empty, operationsInDifferentOrder, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - //todo: what to do with that? - ignore("verify should be failed if there are more proof bytes that needed") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, SerializedAdProof @@ (pf :+ 't'.toByte)) - proof.verify(StateChanges(IndexedSeq.empty, operations, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if there are less proof bytes that needed") { - val (operations, prevDigest, newDigest, pf) = createEnv() - val proof = ADProofs(emptyModifierId, SerializedAdProof @@ pf.init) - proof.verify(StateChanges(IndexedSeq.empty, operations, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("verify should be failed if there are different proof bytes") { - val (operations, prevDigest, newDigest, pf) = createEnv() - pf.update(4, 6.toByte) - val proof = ADProofs(emptyModifierId, pf) - proof.verify(StateChanges(IndexedSeq.empty, operations, IndexedSeq.empty), prevDigest, newDigest) shouldBe 'failure - } - - property("proof is deterministic") { - val pf1 = createEnv()._4 - val pf2 = createEnv()._4 - ADProofs.proofDigest(pf1) shouldBe ADProofs.proofDigest(pf2) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/BlockTransactionsSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/BlockTransactionsSpec.scala deleted file mode 100644 index c3fd1fe644..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/BlockTransactionsSpec.scala +++ /dev/null @@ -1,17 +0,0 @@ -package org.ergoplatform.modifiers.history - -import org.ergoplatform.utils.ErgoPropertyTest - -class BlockTransactionsSpec extends ErgoPropertyTest { - - property("Correct Merkle proofs are generated") { - forAll(invalidBlockTransactionsGen, modifierIdGen){ case (bt, absentTx) => - // for all the transactions presented in a BlockTransactions instance valid proofs should be generated - bt.transactions.forall{t => BlockTransactions.proofValid(bt.digest, bt.proofFor(t.id).get)} shouldBe true - - // no proof should be generated for a transaction which is not there - bt.proofFor(absentTx).isDefined shouldBe false - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/ExtensionCandidateTest.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/ExtensionCandidateTest.scala deleted file mode 100644 index c644abf0d8..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/ExtensionCandidateTest.scala +++ /dev/null @@ -1,47 +0,0 @@ -package org.ergoplatform.modifiers.history - -import org.ergoplatform.modifiers.history.extension.ExtensionCandidate -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.Gen - -class ExtensionCandidateTest extends ErgoPropertyTest { - type KV = (Array[Byte], Array[Byte]) - - property("proofFor should return a valid proof for an existing value") { - forAll { explodedFields: (Seq[KV], KV, Seq[KV]) => - val (left, middle, right) = explodedFields - val fields = left ++ (middle +: right) - - val ext = ExtensionCandidate(fields) - val proof = ext.proofFor(middle._1.clone) - proof shouldBe defined - val nakedLeaf = proof.get.leafData - val numBytesKey = nakedLeaf.head - val key = nakedLeaf.tail.take(numBytesKey) - key shouldBe middle._1 - proof.get.valid(ext.digest) shouldBe true - } - } - - property("batchProofFor should return a valid proof for a set of existing values") { - val modifierIds = Gen.listOf(modifierIdGen) - forAll(modifierIds) { modifiers => - whenever(modifiers.nonEmpty) { - - val fields = NipopowAlgos.packInterlinks(modifiers) - val ext = ExtensionCandidate(fields) - val proof = ext.batchProofFor(fields.map(_._1.clone).toArray: _*) - proof shouldBe defined - proof.get.valid(ext.interlinksDigest) shouldBe true - } - } - } - - property("batchProofFor should return None for a empty fields") { - val fields: Seq[KV] = Seq.empty - val ext = ExtensionCandidate(fields) - val proof = ext.batchProofFor(fields.map(_._1.clone).toArray: _*) - proof shouldBe None - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala deleted file mode 100644 index 0cbd9fa3b8..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/HeadersSpec.scala +++ /dev/null @@ -1,35 +0,0 @@ -package org.ergoplatform.modifiers.history - -import com.google.common.primitives.Longs -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.crypto.hash.Blake2b256 -import scorex.util.ModifierId - -class HeadersSpec extends ErgoPropertyTest { - - val chain: HeaderChain = genHeaderChain(50, diffBitsOpt = None, useRealTs = false) - val genesisId: ModifierId = chain.head.id - - private def mutateNonce(nonce: Array[Byte]): Array[Byte] = { - Longs.toByteArray(Longs.fromByteArray(nonce) + 1) - } - - property("Any field change should lead to different id") { - forAll(defaultHeaderGen) { header => - val initialId = header.id - header.copy(version = (header.version + 1).toByte).id should not equal initialId - header.copy(parentId = initialId).id should not equal initialId - header.copy(ADProofsRoot = Blake2b256(header.ADProofsRoot)).id should not equal initialId - header.copy(transactionsRoot = Blake2b256(header.transactionsRoot)).id should not equal initialId - header.copy(timestamp = header.timestamp + 1).id should not equal initialId - header.copy(nBits = header.nBits + 1).id should not equal initialId - header.copy(height = header.height + 1).id should not equal initialId - header.copy(extensionRoot = Blake2b256(header.extensionRoot)).id should not equal initialId - header.copy(powSolution = header.powSolution.copy(n = mutateNonce(header.powSolution.n))).id should not equal initialId - if(header.version == 1) { - header.copy(powSolution = header.powSolution.copy(d = header.powSolution.d + 1)).id should not equal initialId - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala deleted file mode 100644 index ea2a976724..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala +++ /dev/null @@ -1,226 +0,0 @@ -package org.ergoplatform.modifiers.history - -import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProof, PoPowHeader, PoPowParams} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.generators.ChainGenerator -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import scorex.util.ModifierId -import org.ergoplatform.utils.HistoryTestHelpers - -class PoPowAlgosSpec extends AnyPropSpec with Matchers with HistoryTestHelpers with ChainGenerator { - - private val poPowParams = PoPowParams(30, 30, continuous = false) - private val ChainLength = 10 - - private def toPoPoWChain = (c: Seq[ErgoFullBlock]) => c.map(b => PoPowHeader.fromBlock(b).get) - - property("updateInterlinks") { - val chain = genChain(ChainLength) - val genesis = chain.head - val interlinks = chain.foldLeft(Seq.empty[Seq[ModifierId]]) { case (acc, b) => - acc :+ (if (acc.isEmpty) { - nipopowAlgos.updateInterlinks(b.header, Seq.empty) - } else { - nipopowAlgos.updateInterlinks(b.header, acc.last) - }) - } - - interlinks.foreach { links => - links.head shouldEqual genesis.header.id - links.tail should not contain genesis.header.id - } - - interlinks.zipWithIndex.foreach { case (links, idx) => - if (idx > 0) links.size >= interlinks(idx - 1).size shouldBe true - } - } - - property("packInterlinks") { - val diffInterlinks = Gen.listOfN(255, modifierIdGen).sample.get - val modId = modifierIdGen.sample.get - val sameInterlinks = List.fill(255)(modId) - val packedDiff = nipopowAlgos.interlinksToExtension(diffInterlinks).fields - val packedSame = nipopowAlgos.interlinksToExtension(sameInterlinks).fields - - packedDiff.map(_._1.last).toSet.size shouldEqual diffInterlinks.size - packedSame.map(_._1.last).toSet.size shouldEqual 1 - } - - property("unpackInterlinks") { - val interlinks = Gen.listOfN(255, modifierIdGen).sample.get - val packed = nipopowAlgos.interlinksToExtension(interlinks).fields - val improperlyPacked = packed.map(x => x._1 -> (x._2 :+ (127: Byte))) - - val unpackedTry = NipopowAlgos.unpackInterlinks(packed) - - unpackedTry shouldBe 'success - NipopowAlgos.unpackInterlinks(improperlyPacked) shouldBe 'failure - - unpackedTry.get shouldEqual interlinks - } - - property("proofForInterlinkVector") { - val blockIds = Gen.listOfN(255, modifierIdGen).sample.get - val extension = nipopowAlgos.interlinksToExtension(blockIds) - val proof = NipopowAlgos.proofForInterlinkVector(extension) - proof.get.valid(extension.digest) shouldBe true - } - - property("empty proofForInterlinkVector should be None") { - val blockIds = Seq.empty[ModifierId] - val extension = nipopowAlgos.interlinksToExtension(blockIds) - val proof = NipopowAlgos.proofForInterlinkVector(extension) - proof shouldBe defined - proof.get.proofs should have length 0 - proof.get.indices should have length 0 - } - - property("0 level is always valid for any block") { - val chain = genChain(10) - chain.foreach(x => nipopowAlgos.maxLevelOf(x.header) >= 0 shouldBe true) - } - - property("lowestCommonAncestor - diverging") { - val sizes = Seq(10, 100, 1000) - sizes.foreach { size => - val chain0 = genChain(size) - val branchPoint = chain0(size / 2) - val chain1 = chain0.take(size / 2) ++ genChain(size / 2, branchPoint) - - nipopowAlgos.lowestCommonAncestor(chain0.map(_.header), chain1.map(_.header)) shouldBe Some(branchPoint.header) - } - } - - property("bestArg - always equal for equal proofs") { - val chain0 = genChain(100).map(b => PoPowHeader.fromBlock(b).get) - val proof0 = nipopowAlgos.prove(chain0)(poPowParams).get - val chain1 = genChain(100).map(b => PoPowHeader.fromBlock(b).get) - val proof1 = nipopowAlgos.prove(chain1)(poPowParams).get - val m = poPowParams.m - - proof0.prefix.size shouldEqual proof1.prefix.size - - nipopowAlgos.bestArg(proof0.prefix.map(_.header))(m) shouldEqual nipopowAlgos.bestArg(proof1.prefix.map(_.header))(m) - } - - property("bestArg - always greater for better proof") { - val chain0 = genChain(100).map(b => PoPowHeader.fromBlock(b).get) - val proof0 = nipopowAlgos.prove(chain0)(poPowParams).get - val chain1 = genChain(70).map(b => PoPowHeader.fromBlock(b).get) - val proof1 = nipopowAlgos.prove(chain1)(poPowParams).get - val m = poPowParams.m - - proof0.prefix.size > proof1.prefix.size shouldBe true - - nipopowAlgos.bestArg(proof0.prefix.map(_.header))(m) > nipopowAlgos.bestArg(proof1.prefix.map(_.header))(m) shouldBe true - } - - property("proof(chain) is equivalent to proof(histReader)") { - val poPowParams = PoPowParams(m = 5, k = 6, continuous = false) - val blocksChain = genChain(3000) - val pchain = blocksChain.map(b => PoPowHeader.fromBlock(b).get) - val proof0 = nipopowAlgos.prove(pchain)(poPowParams).get - - val h = generateHistory(true, StateType.Digest, false, - 10000, 10000, 10, None) - val hr = applyChain(h, blocksChain) - val proof1 = nipopowAlgos.prove(hr)(poPowParams).get - - proof0.suffixHead.id shouldBe proof1.suffixHead.id - proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id) - - proof0.prefix.map(_.id).length shouldBe proof1.prefix.map(_.id).length - proof0.prefix.map(_.id).toList shouldBe proof1.prefix.map(_.id).toList - } - - property("proof(histReader) for a header in the past") { - val poPowParams = PoPowParams(5, 6, continuous = false) - val blocksChain = genChain(300) - - val at = 200 - - val h = generateHistory(true, StateType.Digest, false, - 10000, 10000, 10, None) - val hr = applyChain(h, blocksChain.take(at)) - val proof0 = nipopowAlgos.prove(hr, None)(poPowParams).get - - val id = proof0.suffixHead.header.id - - val hrf = applyChain(hr, blocksChain.drop(at)) - val proof1 = nipopowAlgos.prove(hrf, Some(id))(poPowParams).get - - proof0.suffixHead.id shouldBe proof1.suffixHead.id - proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id) - - proof0.prefix.map(_.id).length shouldBe proof1.prefix.map(_.id).length - proof0.prefix.map(_.id).sorted.toList shouldBe proof1.prefix.map(_.id).sorted.toList - } - - property("isBetterThan - marginally longer chain should be better") { - val sizes = Seq(1000) - sizes.foreach { size => - val baseChain = genChain(size) - val branchPoint = baseChain(baseChain.length - 1) - val shortChain = toPoPoWChain(baseChain) - val longChain = toPoPoWChain(baseChain ++ genChain(1, branchPoint).takeRight(1)) - - val shortProof = nipopowAlgos.prove(shortChain)(poPowParams).get - val longProof = nipopowAlgos.prove(longChain)(poPowParams).get - - shortProof.isBetterThan(longProof) shouldBe false - } - } - - property("isBetterThan - a disconnected prefix chain should not win") { - val smallPoPowParams = PoPowParams(50, 1, continuous = false) - val size = 100 - val chain = toPoPoWChain(genChain(size)) - val proof = nipopowAlgos.prove(chain)(smallPoPowParams).get - - val longerChain = toPoPoWChain(genChain(size * 2)) - val longerProof = nipopowAlgos.prove(longerChain)(smallPoPowParams).get - - val disconnectedProofPrefix = proof.prefix.take(proof.prefix.length / 2) ++ longerProof.prefix - val disconnectedProof = NipopowProof(nipopowAlgos, proof.m, proof.k, disconnectedProofPrefix, proof.suffixHead, proof.suffixTail, continuous = false) - proof.isBetterThan(disconnectedProof) shouldBe true - } - - property("hasValidConnections - ensures a connected prefix chain") { - val smallPoPowParams = PoPowParams(5, 5, continuous = false) - val sizes = Seq(100, 200) - sizes.foreach { size => - val chain = toPoPoWChain(genChain(size)) - val randomBlock = toPoPoWChain(genChain(1)).head - val proof = nipopowAlgos.prove(chain)(smallPoPowParams).get - val disconnectedProofPrefix = proof.prefix.updated(proof.prefix.length / 2, randomBlock) - val disconnectedProof = NipopowProof(nipopowAlgos, proof.m, proof.k, disconnectedProofPrefix, proof.suffixHead, proof.suffixTail, continuous = false) - proof.hasValidConnections shouldBe true - disconnectedProof.hasValidConnections shouldBe false - } - } - - property("hasValidConnections - ensures a connected suffix chain") { - val smallPoPowParams = PoPowParams(5, 5, continuous = false) - val sizes = Seq(100, 200) - - sizes.foreach { size => - val chain = toPoPoWChain(genChain(size)) - val randomBlock = genChain(1).head.header - val proof = nipopowAlgos.prove(chain)(smallPoPowParams).get - val disconnectedProofSuffixTail = proof.suffixTail.updated(proof.suffixTail.length / 2, randomBlock) - val disconnectedProof = NipopowProof(nipopowAlgos, proof.m, proof.k, proof.prefix, proof.suffixHead, disconnectedProofSuffixTail, continuous = false) - proof.hasValidConnections shouldBe true - disconnectedProof.hasValidConnections shouldBe false - } - } - - property("hasValidConnections - ensures prefix.last & suffix.head are linked") { - val prefix = toPoPoWChain(genChain(1)) - val suffix = toPoPoWChain(genChain(1)) - NipopowProof(nipopowAlgos, 0, 0, prefix, suffix.head, suffix.tail.map(_.header), continuous = false).hasValidConnections shouldBe false - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowHeaderSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowHeaderSpec.scala deleted file mode 100644 index 978f0f83dc..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/history/PoPowHeaderSpec.scala +++ /dev/null @@ -1,23 +0,0 @@ -package org.ergoplatform.modifiers.history - -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.modifiers.history.popow.PoPowHeader.checkInterlinksProof -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.Gen - -class PoPowHeaderSpec extends ErgoPropertyTest { - - property("Check interlinks proof should be true") { - forAll(Gen.nonEmptyListOf(modifierIdGen)) { interlinks => - val interlinksProof = NipopowAlgos.proofForInterlinkVector(nipopowAlgos.interlinksToExtension(interlinks)).get - checkInterlinksProof(interlinks, interlinksProof) shouldBe true - } - } - - property("Check invalid interlinks proof should be false") { - forAll(Gen.nonEmptyListOf(modifierIdGen), Gen.nonEmptyListOf(modifierIdGen)) { (interlinks1, interlinks2) => - val interlinksProof = NipopowAlgos.proofForInterlinkVector(nipopowAlgos.interlinksToExtension(interlinks2)).get - checkInterlinksProof(interlinks1, interlinksProof) shouldBe false - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala deleted file mode 100644 index 4901e7526b..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ErgoTransactionSpec.scala +++ /dev/null @@ -1,546 +0,0 @@ -package org.ergoplatform.modifiers.mempool - -import io.circe.syntax._ -import org.ergoplatform.ErgoBox._ -import org.ergoplatform.nodeView.ErgoContext -import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} -import org.ergoplatform.sdk.wallet.protocol.context.TransactionContext -import org.ergoplatform.settings.Parameters.MaxBlockCostIncrease -import org.ergoplatform.settings.ValidationRules.{bsBlockTransactionsCost, txAssetsInOneBox} -import org.ergoplatform.settings._ -import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestConstants} -import org.ergoplatform.wallet.boxes.ErgoBoxAssetExtractor -import org.ergoplatform.wallet.interpreter.{ErgoInterpreter, TransactionHintsBag} -import org.ergoplatform.wallet.protocol.context.InputContext -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} -import org.scalacheck.Gen -import sigma.util.BenchmarkUtil -import scorex.crypto.authds.ADKey -import scorex.crypto.hash.Blake2b256 -import scorex.util.encode.Base16 -import scorex.util.{ModifierId, bytesToId} -import sigma.Colls -import sigmastate.AND -import sigmastate.Values.{ByteArrayConstant, ByteConstant, IntConstant, LongArrayConstant, SigmaPropConstant, TrueLeaf} -import sigmastate.crypto.CryptoConstants -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval._ -import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.{ContextExtension, ProverResult} -import sigmastate.eval.Extensions._ - -import scala.util.{Random, Try} - -class ErgoTransactionSpec extends ErgoPropertyTest with ErgoTestConstants { - - private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - - private val emptyModifierId: ModifierId = bytesToId(Array.fill(32)(0.toByte)) - - - private def updateAnAsset(tx: ErgoTransaction, from: IndexedSeq[ErgoBox], deltaFn: Long => Long) = { - val updCandidates = tx.outputCandidates.foldLeft(IndexedSeq[ErgoBoxCandidate]() -> false) { case ((seq, modified), ebc) => - if (modified) { - (seq :+ ebc) -> true - } else { - if (ebc.additionalTokens.nonEmpty && ebc.additionalTokens.exists(t => !java.util.Arrays.equals(t._1.toArray, from.head.id))) { - (seq :+ modifyAsset(ebc, deltaFn, from.head.id.toTokenId)) -> true - } else { - (seq :+ ebc) -> false - } - } - }._1 - tx.copy(outputCandidates = updCandidates) - } - - private def modifyValue(boxCandidate: ErgoBoxCandidate, delta: Long): ErgoBoxCandidate = { - new ErgoBoxCandidate( - boxCandidate.value + delta, - boxCandidate.ergoTree, - boxCandidate.creationHeight, - boxCandidate.additionalTokens, - boxCandidate.additionalRegisters) - } - - private def modifyAsset(boxCandidate: ErgoBoxCandidate, - deltaFn: Long => Long, - idToskip: TokenId): ErgoBoxCandidate = { - val assetId = boxCandidate.additionalTokens.find(t => t._1 != idToskip).get._1 - - val tokens = boxCandidate.additionalTokens.map { case (id, amount) => - if (id == assetId) assetId -> deltaFn(amount) else assetId -> amount - } - - new ErgoBoxCandidate( - boxCandidate.value, - boxCandidate.ergoTree, - boxCandidate.creationHeight, - tokens, - boxCandidate.additionalRegisters) - } - - private def checkTx(from: IndexedSeq[ErgoBox], tx: ErgoTransaction): Try[Int] = { - tx.statelessValidity().flatMap(_ => tx.statefulValidity(from, emptyDataBoxes, emptyStateContext)) - } - - property("serialization vector") { - // test vectors, that specifies transaction json and bytes representation. - // ensures that bytes transaction representation was not changed - - def check(bytesStr: String, bytesToSign: String, jsonStr: String): Unit = { - val bytes = Base16.decode(bytesStr).get - val tx = ErgoTransactionSerializer.parseBytes(bytes) - tx.asJson.noSpaces shouldBe jsonStr - bytesToSign shouldBe Base16.encode(tx.messageToSign) - } - - // simple transfer transaction with 2 inputs and 2 outputs (first is transfer, second is fee) - val height = 1000 - val minerPkHex = "0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942" - val minerPk = Base16.decode(minerPkHex).map { point => - ProveDlog( - CryptoConstants.dlogGroup.ctx.decodePoint(point) - ) - }.get - val inputs: IndexedSeq[Input] = IndexedSeq( - new Input(ADKey @@ Base16.decode("c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f7742").get, - new ProverResult(Base16.decode("b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de4674").get, new ContextExtension(Map()))), - new Input(ADKey @@ Base16.decode("ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead").get, - new ProverResult(Base16.decode("5aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340").get, new ContextExtension(Map()))), - ) - val outputCandidates: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map()), - new ErgoBoxCandidate(1000000L, settings.chainSettings.monetary.feeProposition, height, Colls.emptyColl, Map()) - ) - val tx = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates: IndexedSeq[ErgoBoxCandidate]) - - val bytesToSign = "02c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f77420000ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead00000000028094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070000c0843d1005040004000e36100204cf0f08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304e8070000" - val bytesStr = "02c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f774238b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de467400ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead385aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340000000028094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070000c0843d1005040004000e36100204cf0f08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304e8070000" - val jsonStr = "{\"id\":\"b59ca51f7470f291acc32e84870d00c4fda8b773f38f757f3d65d45265c13da5\",\"inputs\":[{\"boxId\":\"c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f7742\",\"spendingProof\":{\"proofBytes\":\"b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de4674\",\"extension\":{}}},{\"boxId\":\"ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead\",\"spendingProof\":{\"proofBytes\":\"5aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340\",\"extension\":{}}}],\"dataInputs\":[],\"outputs\":[{\"boxId\":\"da288ce9e9a9d39f69634488a8d82c1bf4fb6ddce2f0930d2536016d8167eeb2\",\"value\":1000000000,\"ergoTree\":\"0008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942\",\"assets\":[],\"creationHeight\":1000,\"additionalRegisters\":{},\"transactionId\":\"b59ca51f7470f291acc32e84870d00c4fda8b773f38f757f3d65d45265c13da5\",\"index\":0},{\"boxId\":\"be609af4436111d5592dbd52bc64f6a46a1c0605fd30cd61c74850b7f9875762\",\"value\":1000000,\"ergoTree\":\"1005040004000e36100204cf0f08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304\",\"assets\":[],\"creationHeight\":1000,\"additionalRegisters\":{},\"transactionId\":\"b59ca51f7470f291acc32e84870d00c4fda8b773f38f757f3d65d45265c13da5\",\"index\":1}],\"size\":341}" - Base16.encode(tx.bytes) shouldBe bytesStr - - check(bytesStr, bytesToSign, jsonStr) - - // tx with registers in outputs - val outputCandidates2: IndexedSeq[ErgoBoxCandidate] = IndexedSeq( - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, - Map( - R6 -> IntConstant(10), - R4 -> ByteConstant(1), - R5 -> SigmaPropConstant(minerPk), - R7 -> LongArrayConstant(Array(1L, 2L, 1234123L)), - R8 -> ByteArrayConstant(Base16.decode("123456123456123456123456123456123456123456123456123456123456123456").get), - )), - new ErgoBoxCandidate(1000000000L, minerPk, height, Colls.emptyColl, Map()) - ) - val tx2 = ErgoTransaction(inputs: IndexedSeq[Input], outputCandidates2: IndexedSeq[ErgoBoxCandidate]) - - Base16.encode(tx2.bytes) shouldBe "02c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f774238b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de467400ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead385aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340000000028094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070005020108cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b94204141103020496d396010e211234561234561234561234561234561234561234561234561234561234561234568094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070000" - check(Base16.encode(tx2.bytes), "02c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f77420000ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead00000000028094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070005020108cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b94204141103020496d396010e211234561234561234561234561234561234561234561234561234561234561234568094ebdc030008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942e8070000", - "{\"id\":\"bd04a93f67fda77d89afc38cd8237f142ad5a349405929fd1f7b7f24c4ea2e80\",\"inputs\":[{\"boxId\":\"c95c2ccf55e03cac6659f71ca4df832d28e2375569cec178dcb17f3e2e5f7742\",\"spendingProof\":{\"proofBytes\":\"b4a04b4201da0578be3dac11067b567a73831f35b024a2e623c1f8da230407f63bab62c62ed9b93808b106b5a7e8b1751fa656f4c5de4674\",\"extension\":{}}},{\"boxId\":\"ca796a4fc9c0d746a69702a77bd78b1a80a5ef5bf5713bbd95d93a4f23b27ead\",\"spendingProof\":{\"proofBytes\":\"5aea4d78a234c35accacdf8996b0af5b51e26fee29ea5c05468f23707d31c0df39400127391cd57a70eb856710db48bb9833606e0bf90340\",\"extension\":{}}}],\"dataInputs\":[],\"outputs\":[{\"boxId\":\"1baffa8e5ffce634a8e70530023c16a5c177d2b5ab756ae89a8dce2a23ba433c\",\"value\":1000000000,\"ergoTree\":\"0008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942\",\"assets\":[],\"creationHeight\":1000,\"additionalRegisters\":{\"R4\":\"0201\",\"R5\":\"08cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942\",\"R6\":\"0414\",\"R7\":\"1103020496d39601\",\"R8\":\"0e21123456123456123456123456123456123456123456123456123456123456123456\"},\"transactionId\":\"bd04a93f67fda77d89afc38cd8237f142ad5a349405929fd1f7b7f24c4ea2e80\",\"index\":0},{\"boxId\":\"33eff46f94067b32073d5f81984607be559108f58bc3f53906a1e8db7cf0f708\",\"value\":1000000000,\"ergoTree\":\"0008cd0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942\",\"assets\":[],\"creationHeight\":1000,\"additionalRegisters\":{},\"transactionId\":\"bd04a93f67fda77d89afc38cd8237f142ad5a349405929fd1f7b7f24c4ea2e80\",\"index\":1}],\"size\":356}") -// - // tx with 2 inputs, 1 data input, 3 outputs with tokens 0326df75ea615c18acc6bb4b517ac82795872f388d5d180aac90eaa84de750b942 - check("02e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c6400002e9798d7eb0cd867f6dc29872f80de64c04cef10a99a58d007ef7855f0acbdb9000001f97d1dc4626de22db836270fe1aa004b99970791e4557de8f486f6d433b81195026df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c6403da92a8b8e3ad770008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000200daa4eb6b01aec8d1ff0100da92a8b8e3ad770008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000200daa4eb6b01aec8d1ff0100fa979af8988ce7010008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000000", - "02e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c6400002e9798d7eb0cd867f6dc29872f80de64c04cef10a99a58d007ef7855f0acbdb9000001f97d1dc4626de22db836270fe1aa004b99970791e4557de8f486f6d433b81195026df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c6403da92a8b8e3ad770008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000200daa4eb6b01aec8d1ff0100da92a8b8e3ad770008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000200daa4eb6b01aec8d1ff0100fa979af8988ce7010008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176000000", - "{\"id\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"inputs\":[{\"boxId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}},{\"boxId\":\"2e9798d7eb0cd867f6dc29872f80de64c04cef10a99a58d007ef7855f0acbdb9\",\"spendingProof\":{\"proofBytes\":\"\",\"extension\":{}}}],\"dataInputs\":[{\"boxId\":\"f97d1dc4626de22db836270fe1aa004b99970791e4557de8f486f6d433b81195\"}],\"outputs\":[{\"boxId\":\"69e05b68715caaa4ca58ba59a8c8c7e031d42ad890b05f87021a28617c1e70d5\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":0},{\"boxId\":\"556a9a3ec7880d468e56d44e75898cf8a32f6a07344895fa6b5cf34edf101a59\",\"value\":524940416256346,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[{\"tokenId\":\"6df03fffc9042bf0edb0d0d36d7a675239b83a9080d39716b9aa0a64cccb9963\",\"amount\":226153050},{\"tokenId\":\"e76bf387ab2e63ba8f4e23267bc88265b5fee4950030199e2e2c214334251c64\",\"amount\":536110126}],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":1},{\"boxId\":\"16385b5b83992629909c7e004ed0421229ed3587162ce6f29b2df129472e3909\",\"value\":1016367755463674,\"ergoTree\":\"0008cd02db0ce4d301d6dc0b7a5fbe749588ef4ef68f2c94435020a3c31764ffd36a2176\",\"assets\":[],\"creationHeight\":0,\"additionalRegisters\":{},\"transactionId\":\"663ae91ab7145a4f42b5509e1a2fb0469b7cb46ea87fdfd90e0b4c8ef29c2493\",\"index\":2}],\"size\":329}") - } - - property("a valid transaction is valid") { - forAll(validErgoTransactionGen) { case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe true - } - } - - property("ergo preservation law holds") { - forAll(validErgoTransactionGen, smallPositiveInt) { case ((from, tx), deltaAbs) => - val delta = if (Random.nextBoolean()) -deltaAbs else deltaAbs - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, delta) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess && - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("impossible to create a negative-value output") { - forAll(validErgoTransactionGen) { case (from, tx) => - val negValue = Math.min(Math.abs(Random.nextLong()), Long.MaxValue - tx.outputCandidates.head.value) - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, -(tx.outputCandidates.head.value + negValue)) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("impossible to overflow ergo tokens") { - forAll(validErgoTransactionGen) { case (from, tx) => - val overflowSurplus = (Long.MaxValue - tx.outputCandidates.map(_.value).sum) + 1 - - val wrongTx = tx.copy(outputCandidates = - modifyValue(tx.outputCandidates.head, overflowSurplus) +: tx.outputCandidates.tail) - - wrongTx.statelessValidity().isSuccess shouldBe false - wrongTx.statefulValidity(from, emptyDataBoxes, emptyStateContext).isSuccess shouldBe false - } - } - - property("assets preservation law holds") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ + 1)) shouldBe 'failure - } - } - - property("impossible to create an asset of negative amount") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => -1)) shouldBe 'failure - } - } - - property("impossible to create an asset of zero amount") { - forAll(validErgoTransactionWithAssetsGen) { case (from, tx) => - checkTx(from, updateAnAsset(tx, from, _ => 0)) shouldBe 'failure - } - } - - property("impossible to overflow an asset value") { - val gen = validErgoTransactionGenTemplate(minAssets = 1, maxAssets = 1, maxInputs = 16, propositionGen = trueLeafGen) - forAll(gen) { case (from, tx) => - val tokenOpt = tx.outputCandidates.flatMap(_.additionalTokens.toArray) - .groupBy(_._1).find(_._2.size >= 2) - - whenever(tokenOpt.nonEmpty) { - val tokenId = tokenOpt.get._1 - val tokenAmount = tokenOpt.get._2.map(_._2).sum - - var modified = false - val updCandidates = tx.outputCandidates.map { c => - val updTokens = c.additionalTokens.map { case (id, amount) => - if (!modified && id == tokenId) { - modified = true - id -> ((Long.MaxValue - tokenAmount) + amount + 1) - } else { - id -> amount - } - } - new ErgoBoxCandidate(c.value, c.ergoTree, startHeight, updTokens, c.additionalRegisters) - } - - val wrongTx = tx.copy(outputCandidates = updCandidates) - checkTx(from, wrongTx) shouldBe 'failure - } - } - } - - property("stateful validation should catch false proposition") { - val propositionGen = Gen.const(Constants.FalseLeaf) - val gen = validErgoTransactionGenTemplate(1, 1, 1, propositionGen) - forAll(gen) { case (from, tx) => - tx.statelessValidity().isSuccess shouldBe true - val validity = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext) - validity.isSuccess shouldBe false - val e = validity.failed.get - e.getMessage should startWith(ValidationRules.errorMessage(ValidationRules.txScriptValidation, "", emptyModifierId, ErgoTransaction.modifierTypeId)) - } - } - - property("assets usage correctly affects transaction total cost") { - val txGen = validErgoTransactionGenTemplate(1, 1,16, propositionGen = trueLeafGen) - forAll(txGen) { case (from, tx) => - val initTxCost = tx.statefulValidity(from, emptyDataBoxes, emptyStateContext).get - - // already existing token from one of the inputs - val existingToken = from.flatMap(_.additionalTokens.toArray).toSet.head - // completely new token - val randomToken = (scorex.util.Random.randomBytes().toTokenId, Random.nextInt(100000000).toLong) - - val in0 = from.last - // new token added to the last input - val modifiedIn0 = testBox(in0.value, in0.ergoTree, in0.creationHeight, - in0.additionalTokens.toArray.toSeq :+ randomToken, in0.additionalRegisters, in0.transactionId, in0.index) - val txInMod0 = tx.inputs.last.copy(boxId = modifiedIn0.id) - - val in1 = from.last - // existing token added to the last input - val modifiedIn1 = testBox(in1.value, in1.ergoTree, in1.creationHeight, - in1.additionalTokens.toArray.toSeq :+ existingToken, in1.additionalRegisters, in1.transactionId, in1.index) - val txInMod1 = tx.inputs.last.copy(boxId = modifiedIn1.id) - - val out0 = tx.outputs.last - // new token added to the last output - val modifiedOut0 = testBox(out0.value, out0.ergoTree, out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ randomToken, out0.additionalRegisters, out0.transactionId, out0.index) - // existing token added to the last output - val modifiedOut1 = testBox(out0.value, out0.ergoTree, out0.creationHeight, - out0.additionalTokens.toArray.toSeq :+ existingToken, out0.additionalRegisters, out0.transactionId, out0.index) - - // update transaction inputs and outputs accordingly - val txMod0 = tx.copy(inputs = tx.inputs.init :+ txInMod0) // new token group added to one input - val txMod1 = tx.copy(inputs = tx.inputs.init :+ txInMod1) // existing token added to one input - val txMod2 = tx.copy(inputs = tx.inputs.init :+ txInMod0, // new token group added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut0) - val txMod3 = tx.copy(inputs = tx.inputs.init :+ txInMod1, // existing token added to one input and one output - outputCandidates = tx.outputCandidates.init :+ modifiedOut1) - - val inputIncTxCost0 = txMod0.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get - val inputIncTxCost1 = txMod1.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get - val outputIncTxCost0 = txMod2.statefulValidity(from.init :+ modifiedIn0, emptyDataBoxes, emptyStateContext).get - val outputIncTxCost1 = txMod3.statefulValidity(from.init :+ modifiedIn1, emptyDataBoxes, emptyStateContext).get - - (inputIncTxCost0 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault * 2 // one more group + one more token in total - (inputIncTxCost1 - initTxCost) shouldEqual Parameters.TokenAccessCostDefault // one more token in total - (outputIncTxCost0 - inputIncTxCost0) shouldEqual Parameters.TokenAccessCostDefault * 2 - (outputIncTxCost1 - inputIncTxCost1) shouldEqual Parameters.TokenAccessCostDefault - } - } - - property("spam simulation (transaction validation cost with too many tokens exceeds block limit)") { - val bxsQty = 392 // with greater value test is failing with collection size exception - val (inputs, tx) = validErgoTransactionGenTemplate(1, 1,16).sample.get // it takes too long to test with `forAll` - val tokens = (0 until 255).map(_ => (scorex.util.Random.randomBytes().toTokenId, Random.nextLong)) - val (in, out) = { - val in0 = inputs.head - val out0 = tx.outputs.head - val inputsMod = (0 until bxsQty).map { i => - testBox(10000000000L, in0.ergoTree, in0.creationHeight, - tokens, in0.additionalRegisters, in0.transactionId, i.toShort) - } - val outputsMod = (0 until bxsQty).map { i => - testBox(10000000000L, out0.ergoTree, out0.creationHeight, - tokens, out0.additionalRegisters, out0.transactionId, i.toShort) - } - inputsMod -> outputsMod - } - val inputsPointers = { - val inSample = tx.inputs.head - (0 until bxsQty).map(i => inSample.copy(boxId = in(i).id)) - } - val txMod = tx.copy(inputs = inputsPointers, outputCandidates = out) - val validFailure = txMod.statefulValidity(in, emptyDataBoxes, emptyStateContext) - validFailure.failed.get.getMessage should startWith(ValidationRules.errorMessage(txAssetsInOneBox, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) - } - - property("transaction with too many inputs should be rejected") { - - //we assume that verifier must finish verification of any script in less time than 250K hash calculations - // (for the Blake2b256 hash function over a single block input) - val Timeout: Long = { - val hf = Blake2b256 - - //just in case to heat up JVM - (1 to 5000000).foreach(i => hf(s"$i-$i")) - - val t0 = System.currentTimeMillis() - (1 to 250000).foreach(i => hf(s"$i")) - val t = System.currentTimeMillis() - t - t0 - } - - val gen = validErgoTransactionGenTemplate(0, 0, 2000, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - //check that spam transaction is being rejected quickly - implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - val (validity, time0) = BenchmarkUtil.measureTime(tx.statefulValidity(from, IndexedSeq(), emptyStateContext)) - validity.isSuccess shouldBe false - assert(time0 <= Timeout) - - val cause = validity.failed.get.getMessage - cause should startWith(ValidationRules.errorMessage(bsBlockTransactionsCost, "", emptyModifierId, ErgoTransaction.modifierTypeId).take(30)) - - //check that spam transaction validation with no cost limit is indeed taking too much time - import Parameters._ - val maxCost = (Int.MaxValue - 10) / 10 // cannot use Int.MaxValue directly due to overflow when it is converted to block cost - val ps = Parameters(0, DefaultParameters.updated(MaxBlockCostIncrease, maxCost), emptyVSUpdate) - val sc = new ErgoStateContext(Seq.empty, None, genesisStateDigest, ps, ErgoValidationSettings.initial, - VotingData.empty)(settings) - .upcoming(org.ergoplatform.mining.group.generator, - 0L, - settings.chainSettings.initialNBits, - Array.fill(3)(0.toByte), - ErgoValidationSettingsUpdate.empty, - 0.toByte) - val (_, time) = BenchmarkUtil.measureTime( - tx.statefulValidity(from, IndexedSeq(), sc)(verifier) - ) - - assert(time > Timeout) - } - - property("transaction cost") { - def paramsWith(manualCost: Int) = Parameters( - 0, - Parameters.DefaultParameters + (MaxBlockCostIncrease -> manualCost), - ErgoValidationSettingsUpdate.empty - ) - - val gen = validErgoTransactionGenTemplate(0, 0,10, trueLeafGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - // calculate costs manually - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost - val (outAssets, outAssetsNum) = tx.outAssetsTry.get - val (inAssets, inAssetsNum) = ErgoBoxAssetExtractor.extractAssets(from).get - val totalAssetsAccessCost = - (outAssetsNum + inAssetsNum) * parameters.tokenAccessCost + - (inAssets.size + outAssets.size) * parameters.tokenAccessCost - val scriptsValidationCosts = tx.inputs.size + 1 // +1 for the block to JIT cost scaling - println(s"tx.inputs.size: ${tx.inputs.size}") - println(s"initialCost + totalAssetsAccessCost: ${initialCost + totalAssetsAccessCost}") - val approxCost: Int = (initialCost + totalAssetsAccessCost + scriptsValidationCosts).toInt - - - // check that validation pass if cost limit equals to approximated cost - val sc = stateContextWith(paramsWith(approxCost)) - sc.currentParameters.maxBlockCost shouldBe approxCost - val calculatedCost = tx.statefulValidity(from, IndexedSeq(), sc)(ErgoInterpreter(sc.currentParameters)).get - approxCost - calculatedCost <= 1 shouldBe true - - // transaction exceeds computations limit - val sc2 = stateContextWith(paramsWith(approxCost - 1)) - tx.statefulValidity(from, IndexedSeq(), sc2)(ErgoInterpreter(sc2.currentParameters)) shouldBe 'failure - - // transaction exceeds computations limit due to non-zero accumulatedCost - tx.statefulValidity(from, IndexedSeq(), sc, accumulatedCost = 1)(ErgoInterpreter(sc.currentParameters)) shouldBe 'failure - } - - property("cost accumulated correctly across inputs") { - val accInitCost = 100000 - - def inputCost(tx: ErgoTransaction, from: IndexedSeq[ErgoBox]): Long = { - val idx = 0 - val input = tx.inputs(idx) - val proof = input.spendingProof - val transactionContext = TransactionContext(from, IndexedSeq(), tx) - val inputContext = InputContext(idx.toShort, proof.extension) - - val ctx = new ErgoContext( - emptyStateContext, transactionContext, inputContext, - costLimit = emptyStateContext.currentParameters.maxBlockCost, - initCost = 0) - - val messageToSign = tx.messageToSign - - val inputCost = verifier.verify(from(idx).ergoTree, ctx, proof, messageToSign).get._2 - - inputCost - } - - forAll(smallPositiveInt) { inputsNum => - - val nonTrivialTrueGen = Gen.const(AND(Seq(TrueLeaf, TrueLeaf)).toSigmaProp.treeWithSegregation) - val gen = validErgoTransactionGenTemplate(0, 0, inputsNum, nonTrivialTrueGen) - val (from, tx) = gen.sample.get - tx.statelessValidity().isSuccess shouldBe true - - tx.inputs.length shouldBe inputsNum - - val tokenAccessCost = emptyStateContext.currentParameters.tokenAccessCost - - val txCost = tx.statefulValidity(from, IndexedSeq(), emptyStateContext, accInitCost).get - - val (inAssets, inAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(from).get - val (outAssets, outAssetsNum): (Map[Seq[Byte], Long], Int) = ErgoBoxAssetExtractor.extractAssets(tx.outputs).get - - val assetsCost = inAssetsNum * tokenAccessCost + inAssets.size * tokenAccessCost + - outAssetsNum * tokenAccessCost + outAssets.size * tokenAccessCost - - val unsignedTx = UnsignedErgoTransaction(tx.inputs, tx.dataInputs, tx.outputCandidates) - val signerTxCost = - defaultProver.signInputs(unsignedTx, from, Vector.empty, emptyStateContext, TransactionHintsBag.empty).get._2 - - val signerTxCostWithInitCost = signerTxCost + accInitCost - signerTxCostWithInitCost shouldBe txCost // signer and verifier costs should be the same - - val initialCost: Long = - tx.inputs.size * parameters.inputCost + - tx.dataInputs.size * parameters.dataInputCost + - tx.outputs.size * parameters.outputCost + - ErgoInterpreter.interpreterInitCost + - assetsCost - - txCost shouldBe (accInitCost + initialCost + inputCost(tx, from) * inputsNum) - } - } - - property("monotonic creation height") { - def stateContext(height: Int, blockVersion: Byte): ErgoStateContext = { - val header = defaultHeaderGen.sample.get.copy(version = blockVersion, height = height) - val params = Parameters(LaunchParameters.height, - LaunchParameters.parametersTable.updated(Parameters.BlockVersion, blockVersion), - LaunchParameters.proposedUpdate) - new ErgoStateContext(Seq(header), None, genesisStateDigest, params, ErgoValidationSettings.initial, - VotingData.empty)(settings) - } - - def stateContextForTx(tx: ErgoTransaction, blockVersion: Byte): ErgoStateContext = { - stateContext(tx.outputs.map(_.creationHeight).max, blockVersion) - } - - def updateOutputHeight(box: ErgoBoxCandidate, value: Int): ErgoBoxCandidate = { - new ErgoBoxCandidate(box.value, box.ergoTree, value, box.additionalTokens, box.additionalRegisters) - } - - def updateInputHeight(box: ErgoBox): ErgoBox = { - val creationHeight = scala.util.Random.nextInt(1000) + 1 - new ErgoBox(box.value, box.ergoTree, box.additionalTokens, box.additionalRegisters, - box.transactionId, box.index, creationHeight) - } - - // retuns random transaction along with inputs, - // and a boolean flag, if the latter is true, monotonic creation height rule holds, - // otherwise, it does not hold - val txGen = boxesGenTemplate(minAssets = 0, maxAssets = 5, minInputs = 5, maxInputs = 10, propositionGen = trueLeafGen).map { case (boxes, _) => - boxes.map(updateInputHeight) - }.map{ boxes => - val fixed = Random.nextBoolean() - val maxHeight = boxes.map(_.creationHeight).max - val preUnsignedTx = validUnsignedTransactionFromBoxes(boxes) - val unsignedTx = if(fixed) { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => - val creationHeight = maxHeight + Random.nextInt(3) - updateOutputHeight(out, creationHeight) - }) - } else { - preUnsignedTx.copy(outputCandidates = preUnsignedTx.outputCandidates.map{out => - val creationHeight = maxHeight - (Random.nextInt(maxHeight) + 1) - updateOutputHeight(out, creationHeight) - }) - } - val tx = defaultProver.sign(unsignedTx, boxes, IndexedSeq.empty, emptyStateContext) - .map(ErgoTransaction.apply) - .get - (boxes, tx, fixed) - } - - forAll(txGen){ case (boxes, tx, fixed) => - // with initial block version == 1, monotonic rule does not work - tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 1)).isSuccess shouldBe true - - // with pre-5.0 block version == 2, monotonic rule does not work as well - tx.statefulValidity(boxes, IndexedSeq.empty, stateContextForTx(tx, blockVersion = 2)).isSuccess shouldBe true - - // starting from block version == 3, monotonic rule works, - // so validation fails if transaction is not following the rule (fixed == false) - val ctx3 = stateContextForTx(tx, blockVersion = 3) - if (fixed) { - tx.statefulValidity(boxes, IndexedSeq.empty, ctx3).isSuccess shouldBe true - } else { - val txFailure = tx.statefulValidity(boxes, IndexedSeq.empty, ctx3) - txFailure.isSuccess shouldBe false - val cause = txFailure.toEither.left.get.getMessage - val expectedMessage = ValidationRules.errorMessage(ValidationRules.txMonotonicHeight, "", emptyModifierId, ErgoTransaction.modifierTypeId) - cause should startWith(expectedMessage) - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala deleted file mode 100644 index 7398a9ce5f..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/modifiers/mempool/ExpirationSpecification.scala +++ /dev/null @@ -1,155 +0,0 @@ -package org.ergoplatform.modifiers.mempool - -import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.wallet.interpreter.ErgoInterpreter -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} -import org.scalatest.Assertion -import sigma.Colls -import sigmastate.Values.ShortConstant -import sigmastate.interpreter.{ContextExtension, ProverResult} -import sigmastate.eval._ -import sigmastate.helpers.TestingHelpers._ - -class ExpirationSpecification extends ErgoPropertyTest { - - type Height = Int - - private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - - def falsify(box: ErgoBox): ErgoBox = { - testBox(box.value, - Constants.FalseLeaf, - box.creationHeight, - box.additionalTokens.toArray.toSeq, - box.additionalRegisters, - transactionId = box.transactionId, - boxIndex = box.index) - } - - def constructTest(from: ErgoBox, - heightDelta: Int, - outsConstructor: Height => IndexedSeq[ErgoBoxCandidate], - expectedValidity: Boolean): Assertion = { - // We are filtering out certain heights to avoid problems with improperly generated extension - // at the beginning of a voting epoch - whenever((from.creationHeight + Constants.StoragePeriod + heightDelta) % votingSettings.votingLength != 0) { - val in = Input(from.id, - ProverResult(Array.emptyByteArray, ContextExtension(Map(Constants.StorageIndexVarId -> ShortConstant(0))))) - - val h: Int = from.creationHeight + Constants.StoragePeriod + heightDelta - - val oc = outsConstructor(h).map(c => updateHeight(c, h)) - val tx = ErgoTransaction(inputs = IndexedSeq(in), dataInputs = IndexedSeq(), outputCandidates = oc) - - val fb0 = invalidErgoFullBlockGen.sample.get - val fakeHeader = fb0.header.copy(height = h - 1) - val fb = fb0.copy(fb0.header.copy(height = h, parentId = fakeHeader.id)) - - val updContext = { - val inContext = new ErgoStateContext(Seq(fakeHeader), None, genesisStateDigest, parameters, validationSettingsNoIl, - VotingData.empty)(settings) - inContext.appendFullBlock(fb).get - } - - //serialization roundtrip - val bs = ErgoTransactionSerializer.toBytes(tx) - ErgoTransactionSerializer.parseBytes(bs) shouldBe tx - - tx.statelessValidity().isSuccess shouldBe true - tx.statefulValidity(IndexedSeq(from), emptyDataBoxes, updContext).isSuccess shouldBe expectedValidity - } - } - - property("successful spending w. same value") { - forAll(unspendableErgoBoxGen()) { from => - constructTest(from, 0, _ => IndexedSeq(from), expectedValidity = true) - } - } - - property("successful spending w. max spending") { - forAll(unspendableErgoBoxGen()) { from => - constructTest(from, 0, h => { - val fee = Math.min(parameters.storageFeeFactor * from.bytes.length, from.value) - val feeBoxCandidate = new ErgoBoxCandidate(fee, Constants.TrueLeaf, creationHeight = h) - IndexedSeq(changeValue(from, -fee), Some(feeBoxCandidate)).flatten - }, expectedValidity = true) - } - } - - property("unsuccessful spending due too big storage fee charged") { - forAll(unspendableErgoBoxGen(parameters.storageFeeFactor * 100 + 1, Long.MaxValue)) { from => - constructTest(from, 0, h => { - val fee = Math.min(parameters.storageFeeFactor * from.bytes.length + 1, from.value) - val feeBoxCandidate = new ErgoBoxCandidate(fee, Constants.TrueLeaf, creationHeight = h) - IndexedSeq(changeValue(from, -fee), Some(feeBoxCandidate)).flatten - }, expectedValidity = false) - } - } - - property("unsuccessful spending when more time passed than storage period and charged more than K*storagePeriod") { - forAll(unspendableErgoBoxGen(parameters.storageFeeFactor * 100 + 1, Long.MaxValue)) { from => - constructTest(from, 1, h => { - val fee = Math.min(parameters.storageFeeFactor * from.bytes.length + 1, from.value) - val feeBoxCandidate = new ErgoBoxCandidate(fee, Constants.TrueLeaf, creationHeight = h) - - IndexedSeq(changeValue(from, -fee), Some(feeBoxCandidate)).flatten - }, expectedValidity = false) - } - } - - property("too early spending") { - forAll(unspendableErgoBoxGen()) { from => - constructTest(from, -1, h => { - val fee = Math.min(parameters.storageFeeFactor * from.bytes.length, from.value) - val feeBoxCandidate = new ErgoBoxCandidate(fee, Constants.TrueLeaf, creationHeight = h) - IndexedSeq(changeValue(from, -fee), Some(feeBoxCandidate)).flatten - }, expectedValidity = false) - } - } - - property("script changed spending w. same value") { - forAll(unspendableErgoBoxGen()) { from => - val out = new ErgoBoxCandidate(from.value, Constants.TrueLeaf, from.creationHeight + 1, from.additionalTokens) - constructTest(from, 0, _ => IndexedSeq(out), expectedValidity = false) - } - } - - property("script changed tokens w. same value") { - forAll(unspendableErgoBoxGen()) { from => - whenever(from.additionalTokens.nonEmpty) { - val out = new ErgoBoxCandidate(from.value, from.ergoTree, from.creationHeight + 1, Colls.emptyColl) - constructTest(from, 0, _ => IndexedSeq(out), expectedValidity = false) - } - } - } - - property("script changed register w. same value") { - forAll(unspendableErgoBoxGen()) { from => - whenever(from.additionalRegisters.get(ErgoBox.R4).nonEmpty) { - val out = new ErgoBoxCandidate(from.value, from.ergoTree, from.creationHeight + 1, from.additionalTokens) - constructTest(from, 0, _ => IndexedSeq(out), expectedValidity = false) - } - } - } - - property("spending of whole coin when its value no more than storage fee") { - val out2 = ergoBoxGenNoProp.sample.get - val minValue = out2.value + 1 - - forAll(unspendableErgoBoxGen(minValue, Long.MaxValue)) { from => - val outcome = from.value <= from.bytes.length * parameters.storageFeeFactor - val out1 = new ErgoBoxCandidate(from.value - minValue, Constants.TrueLeaf, creationHeight = from.creationHeight + 1) - constructTest(from, 0, _ => IndexedSeq(out1, out2), expectedValidity = outcome) - } - } - - property("destructing the whole box when its value no more than storage fee") { - forAll(unspendableErgoBoxGen(maxValue = parameters.storageFeeFactor)) { from => - val out = new ErgoBoxCandidate(from.value, Constants.TrueLeaf, creationHeight = from.creationHeight + 1) - constructTest(from, 0, _ => IndexedSeq(out), expectedValidity = true) - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala deleted file mode 100644 index 8271050c45..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ActivePeerFilteringSpecification.scala +++ /dev/null @@ -1,44 +0,0 @@ -package org.ergoplatform.network - -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.peer.PeerInfo -import scorex.core.network.peer.PeerManager.ReceivableMessages.SeenPeers - -import java.net.{InetAddress, InetSocketAddress} - -class ActivePeerFilteringSpecification extends ErgoPropertyTest { - - private val filter: SeenPeers = SeenPeers(5) - - private def newPeer(address: String, port: Int, lastHandshakeOffset: Long): (InetSocketAddress, PeerInfo) = { - val addr = new InetSocketAddress(address, port) - val pi = PeerInfo( - defaultPeerSpec.copy(declaredAddress = Some(addr)), - System.currentTimeMillis() - lastHandshakeOffset, - None, - System.currentTimeMillis() - lastHandshakeOffset - ) - (addr, pi) - } - - private val knownPeers: Map[InetSocketAddress, PeerInfo] = Map( - newPeer("1.2.3.4", 1234, 12340), // blacklisted - newPeer("2.3.4.1", 2341, 23410), - newPeer("3.4.1.2", 3412, 34120), - newPeer("4.1.2.3", 4123, 41230 + filter.limit), // over limit - ) - - private val blacklistedPeers: Seq[InetAddress] = Seq(InetAddress.getByName("1.2.3.4")) - - private val correct: Seq[PeerInfo] = knownPeers.toSeq.slice(1,3).map(_._2) - - property("time based activity filter") { - - val result: Seq[PeerInfo] = - filter.choose(knownPeers, blacklistedPeers, null).sortBy(-_.lastHandshake) // sort to undo Random.shuffle - - result.size shouldBe 2 - result shouldBe correct - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/DecodingUtils.scala b/ergo-core/src/test/scala/org/ergoplatform/network/DecodingUtils.scala deleted file mode 100644 index cecc865a23..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/DecodingUtils.scala +++ /dev/null @@ -1,61 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -// Common functions used in parsers, collected in one place to be easily understood and rewritten into other languages -trait DecodingUtils { - - /** - * Read unsigned byte - */ - def getUByte(buf: ByteBuffer): Int = getByte(buf) & 0xFF - - /** - * Read signed byte - */ - def getByte(buf: ByteBuffer): Byte = buf.get - - /** - * Reading up to 64 bits VLQ-encoded value. The value is considered to be signed. - * Can be read less than 64 bytes! - * See https://en.wikipedia.org/wiki/Variable-length_quantity - */ - def getULong(buf: ByteBuffer): Long = { - var result: Long = 0 - var shift = 0 - while (shift < 64) { - val b = getByte(buf) - result = result | ((b & 0x7F).toLong << shift) - if ((b & 0x80) == 0) return result - shift += 7 - } - throw new IllegalStateException("Trying to read long, but more bytes than needed found") - } - - /** - * Read signed int (32 bits) value - **/ - def getInt(buf: ByteBuffer): Int = { - // should only be changed simultaneously with `putInt` - decodeZigZagInt(getULong(buf).toInt) - } - - - /** - * Read `size` bytes - */ - def getBytes(buf: ByteBuffer, size: Int): Array[Byte] = { - val res = new Array[Byte](size) - buf.get(res) - res - } - - /** - * Decode ZigZag-encoded (32 bits) integer - */ - def decodeZigZagInt(n: Int): Int = { - // source: http://github.com/google/protobuf/blob/a7252bf42df8f0841cf3a0c85fdbf1a5172adecb/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L553 - (n >>> 1) ^ -(n & 1) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ElementPartitionerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ElementPartitionerSpecification.scala deleted file mode 100644 index 3104f18265..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ElementPartitionerSpecification.scala +++ /dev/null @@ -1,121 +0,0 @@ -package org.ergoplatform.network - -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks - - -class ElementPartitionerSpecification - extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers { - - def distribute[B, T, I](buckets: Iterable[B], - maxElements: Int, - minElementsPerBucket: Int, - maxElementsPerBucket: Int - )(fetchMax: Int => Map[T, Seq[I]]): Map[(B, T), Seq[I]] = { - val peersCount = buckets.size - val maxElementsToFetch = Math.min(maxElements, peersCount * maxElementsPerBucket) - val fetched = if (maxElementsToFetch <= 0) { - Map.empty[T, Seq[I]] - } else { - fetchMax(maxElementsToFetch) - } - ElementPartitioner.distribute(buckets, minElementsPerBucket, fetched) - } - - property("elements should be evenly distributed in buckets limited by bucket size") { - forAll(Gen.nonEmptyListOf(Gen.alphaNumChar), Gen.nonEmptyListOf(Gen.alphaNumChar)) { - case (buckets, elements) => - val (elemsType_1, elemsType_2) = elements.splitAt(elements.size / 2) - val elemsByBucket = - distribute(buckets, Integer.MAX_VALUE, 1, 5) { count => - count shouldBe buckets.size * 5 - Map("A" -> elemsType_1.take(count), "B" -> elemsType_2.take(count)) - } - elemsByBucket shouldNot be(empty) - elemsByBucket.forall(_._2.nonEmpty) shouldBe true - elemsByBucket.map(_._2.size).toSet.size <= 2 shouldBe true // evenly distributed - elemsByBucket.forall(_._2.size <= 5) shouldBe true // max sized batches - } - } - - property("elements should never reach max elements") { - forAll(Gen.nonEmptyListOf(Gen.alphaNumChar), Gen.nonEmptyListOf(Gen.alphaNumChar)) { - case (buckets, elements) => - val (elemsType_1, elemsType_2) = elements.splitAt(elements.size / 2) - val elemsByBucket = distribute(buckets, 5, 1, 100) { count => - count shouldBe 5 - Map("A" -> elemsType_1.take(count), "B" -> elemsType_2.take(count)) - } - elemsByBucket.map(_._2.size).sum <= 2 * 5 shouldBe true // max size of elements - } - } - - property( - "bucket should contain less elements than minElementsPerBucket only if not enough elements is available" - ) { - forAll(Gen.listOf(Gen.alphaNumChar), Gen.listOf(Gen.alphaNumChar)) { - case (buckets, elements) => - val elemsByBucket = - distribute(buckets, Integer.MAX_VALUE, 5, 10) { count => - assert(count <= 10 * buckets.size) - Map("A" -> elements.take(count)) - } - // if there is only 4 elements available to download, then bucket may contain only 4 elements regardless of minElementsPerBucket=5 - if (elements.size >= 5) { - elemsByBucket.map(_._2.size).foreach { count => - assert(count >= 5 && count <= 10) - } - } - } - } - - property("empty buckets or elements cannot be partitioned") { - distribute(List.empty, Integer.MAX_VALUE, 1, 5)(_ => Map("A" -> List(1))) - .size shouldBe 0 - distribute(List(1), Integer.MAX_VALUE, 1, 5)(_ => Map.empty[String, Seq[Int]]) - .size shouldBe 0 - distribute(List.empty, Integer.MAX_VALUE, 1, 5)(_ => Map.empty[String, Seq[Int]]) - .size shouldBe 0 - } - - property("0 or negative count of elements to fetch cannot be partitioned") { - distribute(List.empty, -1, 1, 5)(_ => Map("A" -> List(1))) - .size shouldBe 0 - distribute(List.empty, 5, 1, 0)(_ => Map("A" -> List(1))) - .size shouldBe 0 - } - - property("less or equal elements than buckets should return one element per bucket") { - distribute(List(1, 2, 3), Integer.MAX_VALUE, 1, 5) { _ => - Map("A" -> List(1)) - } shouldBe Map((1, "A") -> List(1)) - } - - property("elements should be distributed into bucket-types") { - distribute(List(1, 2), Integer.MAX_VALUE, 1, 1) { _ => - Map("A" -> List(1, 2), "B" -> List(1, 2), "C" -> List(1, 2)) - } shouldBe Map( - (2, "B") -> List(2), - (1, "C") -> List(1), - (1, "B") -> List(1), - (1, "A") -> List(1), - (2, "C") -> List(2), - (2, "A") -> List(2) - ) - } - - property( - "minElementsPerBucket constraint should not be used if there is less elements available" - ) { - val elems = - distribute(List(1), Integer.MAX_VALUE, 100, 1) { _ => - Map("A" -> List(1)) - } - elems.size shouldBe 1 - elems.head._2.size shouldBe 1 - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala deleted file mode 100644 index 2430aa7728..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala +++ /dev/null @@ -1,452 +0,0 @@ -package org.ergoplatform.network - -import akka.actor.{ActorRef, ActorSystem, Cancellable, Props} -import akka.testkit.TestProbe -import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ -import org.ergoplatform.nodeView.ErgoNodeViewHolder -import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader, ErgoSyncInfoMessageSpec, ErgoSyncInfoV2} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.nodeView.state.{StateType, UtxoState} -import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.HistoryTestHelpers -import org.ergoplatform.wallet.utils.FileUtils -import org.scalacheck.Gen -import org.scalatest.concurrent.Eventually -import org.scalatest.matchers.should.Matchers -import scorex.core.PersistentNodeViewModifier -import scorex.core.network.ModifiersStatus.{Received, Unknown} -import scorex.core.network.NetworkController.ReceivableMessages.SendToNetwork -import scorex.core.network.message._ -import scorex.core.network.peer.PeerInfo -import scorex.core.network.{ConnectedPeer, DeliveryTracker} -import scorex.core.serialization.ErgoSerializer -import scorex.testkit.utils.AkkaFixture - -import scala.concurrent.duration.{Duration, _} -import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor} -import scala.language.postfixOps - -class ErgoNodeViewSynchronizerSpecification extends HistoryTestHelpers with Matchers with FileUtils with Eventually { - - // ToDo: factor this out of here and NVHTests? - private def withFixture(testCode: SynchronizerFixture => Any): Unit = { - val fixture = new SynchronizerFixture - try { - testCode(fixture) - } - finally { - Await.result(fixture.system.terminate(), Duration.Inf) - } - } - - private def withFixture2(testCode: Synchronizer2Fixture => Any): Unit = { - val fixture = new Synchronizer2Fixture - try { - testCode(fixture) - } - finally { - Await.result(fixture.system.terminate(), Duration.Inf) - } - } - - class NodeViewHolderMock extends ErgoNodeViewHolder[UtxoState](settings) - - class SynchronizerMock(networkControllerRef: ActorRef, - viewHolderRef: ActorRef, - syncInfoSpec: ErgoSyncInfoMessageSpec.type, - settings: ErgoSettings, - syncTracker: ErgoSyncTracker, - deliveryTracker: DeliveryTracker) - (implicit ec: ExecutionContext) extends ErgoNodeViewSynchronizer( - networkControllerRef, - viewHolderRef, - syncInfoSpec, - settings, - syncTracker, - deliveryTracker)(ec) { - - protected def broadcastInvForNewModifier(mod: PersistentNodeViewModifier): Unit = { - mod match { - case fb: ErgoFullBlock if fb.header.isNew(1.hour) => - fb.toSeq.foreach(s => broadcastModifierInv(s)) - case h: Header if h.isNew(1.hour) => - broadcastModifierInv(h) - case _ => - } - } - } - - override implicit val patienceConfig: PatienceConfig = PatienceConfig(2.seconds, 100.millis) - val history = generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, blocksToKeep = -1) - val chain = genHeaderChain(2000, history, diffBitsOpt = None, useRealTs = false) - val localChain = chain.take(1000) - val altchain = genHeaderChain(1000, history, diffBitsOpt = None, useRealTs = false) - - val forkedChain = { - val c = localChain.take(1000 - 512) - c ++ genHeaderChain(512, Some(c.last), diffBitsOpt = None, useRealTs = false).tail - } - val forkedHeight = forkedChain.last.height - - val localHistoryGen: Gen[HT] = { - require(history.isEmpty) - applyHeaderChain(history, localChain) - } - - val localStateGen: Gen[WrappedUtxoState] = - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)) - - def semanticallyValidModifier(state: UTXO_ST): PM = { - statefulyValidFullBlock(state.asInstanceOf[WrappedUtxoState]) - } - - def semanticallyInvalidModifier(state: UTXO_ST): PM = invalidErgoFullBlockGen.sample.get - - def totallyValidModifier(history: HT, state: UTXO_ST): PM = { - val parentOpt = history.bestFullBlockOpt - validFullBlock(parentOpt, state.asInstanceOf[WrappedUtxoState]).header - } - - def totallyValidModifiers(history: HT, state: UTXO_ST, count: Int): Seq[PM] = { - require(count >= 1) - val headerOpt = history.bestFullBlockOpt - (0 until count).foldLeft((headerOpt, Seq.empty[PM])) { case (acc, _) => - val pm = validFullBlock(headerOpt, state.asInstanceOf[WrappedUtxoState]) - (Some(pm), acc._2 :+ pm) - }._2.map(_.asInstanceOf[ErgoFullBlock].header) - } - - def nodeViewSynchronizer(implicit system: ActorSystem): - (ActorRef, ActorRef, SI, PM, TX, ConnectedPeer, TestProbe, TestProbe, TestProbe, ErgoSerializer[PM], DeliveryTracker) = { - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val h = localHistoryGen.sample.get - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val s = localStateGen.sample.get - val settings = ErgoSettings.read() - val pool = ErgoMemPool.empty(settings) - implicit val ec: ExecutionContextExecutor = system.dispatcher - val ncProbe = TestProbe("NetworkControllerProbe") - val pchProbe = TestProbe("PeerHandlerProbe") - val eventListener = TestProbe("EventListener") - val syncTracker = ErgoSyncTracker(settings.scorexSettings.network) - val deliveryTracker: DeliveryTracker = DeliveryTracker.empty(settings) - - // each test should always start with empty history - deleteRecursive(ErgoHistory.historyDir(settings)) - val nodeViewHolderMockRef = system.actorOf(Props(new NodeViewHolderMock)) - - val synchronizerMockRef = system.actorOf(Props( - new SynchronizerMock( - ncProbe.ref, - nodeViewHolderMockRef, - ErgoSyncInfoMessageSpec, - settings, - syncTracker, - deliveryTracker) - )) - val m = totallyValidModifier(h, s) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val tx = validErgoTransactionGenTemplate(0, 0).sample.get._2 - - val peerInfo = PeerInfo(defaultPeerSpec, System.currentTimeMillis()) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val p: ConnectedPeer = ConnectedPeer( - connectionIdGen.sample.get, - pchProbe.ref, - Some(peerInfo) - ) - synchronizerMockRef ! ChangedHistory(history) - synchronizerMockRef ! ChangedMempool(pool) - val serializer: ErgoSerializer[PM] = HeaderSerializer.asInstanceOf[ErgoSerializer[PM]] - (synchronizerMockRef, nodeViewHolderMockRef, h.syncInfoV1, m, tx, p, pchProbe, ncProbe, eventListener, serializer, deliveryTracker) - } - - class SynchronizerFixture extends AkkaFixture { - @SuppressWarnings(Array("org.wartremover.warts.PublicInference")) - val (synchronizer, nodeViewHolder, syncInfo, mod, tx, peer, pchProbe, ncProbe, eventListener, modSerializer, deliveryTracker) = nodeViewSynchronizer - } - - class Synchronizer2Fixture extends AkkaFixture { - implicit val ec: ExecutionContextExecutor = system.dispatcher - val ncProbe = TestProbe("NetworkControllerProbe") - val pchProbe = TestProbe("PeerHandlerProbe") - val syncTracker = ErgoSyncTracker(settings.scorexSettings.network) - val deliveryTracker: DeliveryTracker = DeliveryTracker.empty(settings) - - // each test should always start with empty history - deleteRecursive(ErgoHistory.historyDir(settings)) - val nodeViewHolderMockRef = system.actorOf(Props(new NodeViewHolderMock)) - - val synchronizerMockRef = system.actorOf(Props( - new SynchronizerMock( - ncProbe.ref, - nodeViewHolderMockRef, - ErgoSyncInfoMessageSpec, - settings, - syncTracker, - deliveryTracker) - )) - - val peerInfo = PeerInfo(defaultPeerSpec, System.currentTimeMillis()) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val peer: ConnectedPeer = ConnectedPeer( - connectionIdGen.sample.get, - pchProbe.ref, - Some(peerInfo) - ) - } - - property("NodeViewSynchronizer: Message: SyncInfoSpec V2 - younger peer") { - withFixture { ctx => - import ctx._ - - val emptySync = ErgoSyncInfoV2(Seq.empty) - - // Neighbour is sending - val msgBytes = ErgoSyncInfoMessageSpec.toBytes(emptySync) - - // we check that in case of neighbour with empty history (it has no any blocks), - // inv message with our block ids will be sent - synchronizer ! Message(ErgoSyncInfoMessageSpec, Left(msgBytes), Some(peer)) - ncProbe.fishForMessage(3 seconds) { case m => - m match { - case stn: SendToNetwork => - val msg = stn.message - msg.spec.messageCode == InvSpec.messageCode && - msg.data.get.asInstanceOf[InvData].ids.head == chain.head.id - case _ => false - } - } - } - } - - property("NodeViewSynchronizer: receiving valid header") { - withFixture { ctx => - import ctx._ - deliveryTracker.reset() - deliveryTracker.setRequested(Header.modifierTypeId, chain.take(1001).last.id, peer)(_ => Cancellable.alreadyCancelled) - val olderChain = chain.take(1001) - val modData = ModifiersData(Header.modifierTypeId, Map(olderChain.last.id -> olderChain.last.bytes)) - val modSpec = ModifiersSpec - synchronizer ! Message(modSpec, Left(modSpec.toBytes(modData)), Some(peer)) - // desired state of submitting valid headers is Received - eventually { - deliveryTracker.status(olderChain.last.id, Header.modifierTypeId, Seq.empty) shouldBe Received - } - } - } - - property("NodeViewSynchronizer: apply continuation header from syncV2 and download its block") { - withFixture2 { ctx => - import ctx._ - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 100.millis) - - // we generate and apply existing base chain - val hhistory = ErgoHistory.readOrGenerate(settings)(null) - val baseChain = genHeaderChain(_.size > 4, None, hhistory.difficultyCalculator, None, false) - baseChain.headers.foreach(hhistory.append) - val bestHeaderOpt = hhistory.bestHeaderOpt - - // then a continuation chain that will be part of the syncV2 message - val continuationChain = genHeaderChain(_.size > 4, bestHeaderOpt, hhistory.difficultyCalculator, None, false).tail - - // sync message carries best header of our base change + continuation chain whose Head header is supposed to be applied - val sync = ErgoSyncInfoV2(continuationChain.headers) - val msgBytes = ErgoSyncInfoMessageSpec.toBytes(sync) - - // send this sync msg to synchronizer which should apply the header following the common header from base chain - synchronizerMockRef ! Message(ErgoSyncInfoMessageSpec, Left(msgBytes), Some(peer)) - val appliedHeader = continuationChain.headers.head - // calculate block sections for applied header and test whether they were attempted to be downloaded from remote peer - var remainingSectionIds = hhistory.requiredModifiersForHeader(appliedHeader).groupBy(_._1).mapValues(_.map(_._2).head) - while (remainingSectionIds.nonEmpty) { - ncProbe.fishForMessage(3 seconds) { case m => - m match { - case stn: SendToNetwork if stn.message.spec.messageCode == RequestModifierSpec.messageCode => - val invData = stn.message.data.get.asInstanceOf[InvData] - remainingSectionIds.exists { case (sectionTypeId, sectionId) => - val sectionFound = invData.typeId == sectionTypeId && invData.ids.head == sectionId - if (sectionFound) { - remainingSectionIds = remainingSectionIds - sectionTypeId - } - sectionFound - } - case _ => - false - } - } - } - eventually { - // test whether applied header was actually persisted to history - val hist = ErgoHistory.readOrGenerate(settings)(null) - hist.bestHeaderIdOpt.get shouldBe appliedHeader.id - } - } - } - - property("NodeViewSynchronizer: receiving out-of-order header should request it again") { - withFixture2 { ctx => - import ctx._ - - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - - def sendHeader(header: Header): Unit = { - deliveryTracker.setRequested(Header.modifierTypeId, header.id, peer)(_ => Cancellable.alreadyCancelled) - val modData = ModifiersData(Header.modifierTypeId, Map(header.id -> header.bytes)) - val modSpec = ModifiersSpec - synchronizerMockRef ! Message(modSpec, Left(modSpec.toBytes(modData)), Some(peer)) - } - - deliveryTracker.reset() - - // we generate fork of two headers, starting from the parent of the best header - // so the depth of the rollback is 1, and the fork bypasses the best chain by 1 header - val hhistory = ErgoHistory.readOrGenerate(settings)(null) - val newHeaders = genHeaderChain(2, hhistory, diffBitsOpt = None, useRealTs = false).headers - val newHistory = newHeaders.foldLeft(hhistory) { case (hist, header) => hist.append(header).get._1 } - val parentOpt = newHistory.lastHeaders(2).headOption - val smallFork = genHeaderChain(_.size > 2, parentOpt, newHistory.difficultyCalculator, None, false) - val secondForkHeader = smallFork.last - - sendHeader(secondForkHeader) - // we submit header at best height + 1, but with parent not known, the status should be unknown, - // so after some time the header could be downloaded again (when the parent may be known) - eventually { - deliveryTracker.status(secondForkHeader.id, Header.modifierTypeId, Seq.empty) shouldBe Unknown - } - } - } - - - property("NodeViewSynchronizer: longer fork is applied and shorter is not") { - withFixture2 { ctx => - import ctx._ - - def sendHeader(block: ErgoFullBlock): Unit = { - deliveryTracker.setRequested(Header.modifierTypeId, block.header.id, peer)(_ => Cancellable.alreadyCancelled) - val modData = ModifiersData(Header.modifierTypeId, Map(block.header.id -> block.header.bytes)) - synchronizerMockRef ! Message(ModifiersSpec, Left(ModifiersSpec.toBytes(modData)), Some(peer)) - } - - def sendBlockSection(block: BlockSection): Unit = { - deliveryTracker.setRequested(block.modifierTypeId, block.id, peer)(_ => Cancellable.alreadyCancelled) - val modData = ModifiersData(block.modifierTypeId, Map(block.id -> block.bytes)) - synchronizerMockRef ! Message(ModifiersSpec, Left(ModifiersSpec.toBytes(modData)), Some(peer)) - } - - def sendBlock(block: ErgoFullBlock): Unit = { - sendBlockSection(block.blockTransactions) - sendBlockSection(block.extension) - block.adProofs.foreach(sendBlockSection(_)) - } - - deliveryTracker.reset() - - val hist = ErgoHistory.readOrGenerate(settings)(null) - // generate smaller fork that is going to be reverted after applying a bigger fork - val smallFork = genChain(4, hist) - - smallFork.foreach(sendHeader) - // history should eventually contain all smaller fork headers - eventually { - smallFork.forall(block => hist.contains(block.id)) - } - smallFork.foreach(sendBlock) - // history should eventually contain smaller fork block parts - eventually { - smallFork.forall(block => hist.contains(block.extension.id) && hist.contains(block.blockTransactions.id)) - } - // generate bigger fork that is going to win over smaller fork that is to be reverted - val bigFork = genChain(20, hist, extension = emptyExtension) - - bigFork.foreach(sendHeader) - // history should revert all smaller fork headers - eventually { - smallFork.forall(block => !hist.contains(block.id)) - } - bigFork.foreach(sendBlock) - // history should revert all smaller fork block parts - eventually { - smallFork.forall(block => !hist.contains(block.extension.id) && !hist.contains(block.blockTransactions.id)) - } - } - } - - property("NodeViewSynchronizer: Message: SyncInfoSpec V2 - older peer") { - withFixture { ctx => - import ctx._ - - val sync = ErgoSyncInfoV2(Seq(chain.last)) - - // Neighbour is sending - val msgBytes = ErgoSyncInfoMessageSpec.toBytes(sync) - - // we check that in case of neighbour with older history (it has more blocks), - // sync message will be sent by our node (to get invs from the neighbour), - // sync message will consist of 4 headers - synchronizer ! Message(ErgoSyncInfoMessageSpec, Left(msgBytes), Some(peer)) - ncProbe.fishForMessage(3 seconds) { case m => - m match { - case stn: SendToNetwork => - val msg = stn.message - val headers = msg.data.get.asInstanceOf[ErgoSyncInfoV2].lastHeaders - msg.spec.messageCode == ErgoSyncInfoMessageSpec.messageCode && headers.length == 4 - case _ => false - } - } - } - } - - property("NodeViewSynchronizer: Message: SyncInfoSpec V2 - unknown peer") { - withFixture { ctx => - import ctx._ - - val sync = ErgoSyncInfoV2(Seq(altchain.last)) - - // Neighbour is sending - val msgBytes = ErgoSyncInfoMessageSpec.toBytes(sync) - - // we check that in case of neighbour with older history (it has more blocks), - // sync message will be sent by our node (to get invs from the neighbour), - // sync message will consist of 4 headers - synchronizer ! Message(ErgoSyncInfoMessageSpec, Left(msgBytes), Some(peer)) - ncProbe.fishForMessage(3 seconds) { case m => - m match { - case stn: SendToNetwork => - val msg = stn.message - val headers = msg.data.get.asInstanceOf[ErgoSyncInfoV2].lastHeaders - msg.spec.messageCode == ErgoSyncInfoMessageSpec.messageCode && headers.length == 4 - case _ => false - } - } - } - } - - property("NodeViewSynchronizer: Message: SyncInfoSpec V2 - forked peer") { - withFixture { ctx => - import ctx._ - - val sync = ErgoSyncInfoV2(ErgoHistoryReader.FullV2SyncOffsets.map(offset => forkedChain.apply(forkedHeight - offset - 1))) - - // Neighbour is sending - val msgBytes = ErgoSyncInfoMessageSpec.toBytes(sync) - val invSpec = InvSpec - // we check that in case of neighbour with older history (it has more blocks), - // invs (extension for the forked peer) will be sent to the peer - synchronizer ! Message(ErgoSyncInfoMessageSpec, Left(msgBytes), Some(peer)) - ncProbe.fishForMessage(3 seconds) { case m => - m match { - case stn: SendToNetwork => - val msg = stn.message - msg.spec.messageCode == invSpec.messageCode - case _ => false - } - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala deleted file mode 100644 index 3768260d27..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncInfoSpecification.scala +++ /dev/null @@ -1,73 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -import com.google.common.primitives.Ints -import org.ergoplatform.nodeView.history.{ErgoSyncInfoMessageSpec, ErgoSyncInfoV1} -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.message.{Message, MessageSerializer} -import scorex.crypto.hash -import scorex.util.ModifierId -import scorex.util.encode.Base16 - - -/** - * syncInfo is a message sent from one peer to another in order to get (and agree) on synchronization status - * - * syncInfo v1 is about a sequence of header ids just - */ -class ErgoSyncInfoSpecification extends ErgoPropertyTest with DecodingUtils { - - property("sync info v1 reference parser") { - val magic = Array(1: Byte, 0: Byte, 2: Byte, 4: Byte) // mainnet magic - val syncSpec = ErgoSyncInfoMessageSpec - - val lastHeaderId = Array.fill(16)(1: Byte) ++ Array.fill(16)(2: Byte) - - val syncInfo = ErgoSyncInfoV1(Seq(ModifierId @@ Base16.encode(lastHeaderId))) - - val syncMessage = Message(syncSpec, Right(syncInfo), None) - - val ms = new MessageSerializer(Seq(syncSpec), magic) - - val bs = ms.serialize(syncMessage).toArray - val bsString = Base16.encode(bs) - - // test vector got via high-level API - bsString shouldBe "0100020441000000214f904163010101010101010101010101010101010102020202020202020202020202020202" - - val bb = ByteBuffer.wrap(bs) - - // simple reference parser below - - // read network magic (network id) bytes (4 bytes) - val magicRead = getBytes(bb, 4) - magicRead.toIndexedSeq shouldBe magic.toIndexedSeq - - // read message type id - val messageCode = getByte(bb) - messageCode shouldBe syncSpec.messageCode // 65 (in dec) - - // read message length (4 bytes) - val messageLength = Ints.fromByteArray(getBytes(bb,4)) - - messageLength shouldBe 33 - - // read message length (4 bytes) - val checkSum = getBytes(bb, 4) - - // read number of headers, up to 8 bytes, but there are app-level limits (400 in reference client) - val headersCount = getULong(bb).toByte // should read one byte only - - headersCount shouldBe 1.toByte - - // read header ids, one-by-one - val headerId = getBytes(bb, 32) - - headerId.toIndexedSeq shouldBe lastHeaderId.toIndexedSeq - - // checksum must be equal to first 4 bytes of message payload - checkSum shouldBe hash.Blake2b256(headersCount +: headerId).take(4) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala deleted file mode 100644 index b96081117e..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ErgoSyncTrackerSpecification.scala +++ /dev/null @@ -1,49 +0,0 @@ -package org.ergoplatform.network - -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.consensus.{Older, Younger} -import scorex.core.network.{ConnectedPeer, ConnectionId, Incoming} -import scorex.core.network.peer.PeerInfo - -class ErgoSyncTrackerSpecification extends ErgoPropertyTest { - property("getters test") { - val time = 10L - val peerInfo = PeerInfo(defaultPeerSpec, time, Some(Incoming), 5L) - val cid = ConnectionId(inetAddr1, inetAddr2, Incoming) - val connectedPeer = ConnectedPeer(cid, handlerRef = null, Some(peerInfo)) - val syncTracker = ErgoSyncTracker(settings.scorexSettings.network) - - val height = 1000 - // add peer to sync - syncTracker.updateStatus(connectedPeer, Younger, Some(height)) - syncTracker.maxHeight() shouldBe Some(height) - syncTracker.statuses(connectedPeer) shouldBe ErgoPeerStatus(connectedPeer, Younger, height, None, None) - // updating status should change status and height of existing peer - syncTracker.updateStatus(connectedPeer, Older, Some(height+1)) - syncTracker.maxHeight() shouldBe Some(height + 1) - syncTracker.getStatus(connectedPeer) shouldBe Some(Older) - - syncTracker.peersByStatus.apply(Older).head shouldBe connectedPeer - // peer should not be synced yet - syncTracker.notSyncedOrOutdated(connectedPeer) shouldBe true - syncTracker.outdatedPeers shouldBe Vector.empty - // peer should be ready for sync - syncTracker.peersToSyncWith().head shouldBe connectedPeer - syncTracker.updateLastSyncSentTime(connectedPeer) - // peer should be synced now - syncTracker.notSyncedOrOutdated(connectedPeer) shouldBe false - - syncTracker.clearStatus(connectedPeer) - // peer should not be tracked anymore - syncTracker.getStatus(connectedPeer) shouldBe None - syncTracker.peersByStatus.isEmpty shouldBe true - syncTracker.statuses.get(connectedPeer) shouldBe None - syncTracker.peersToSyncWith().length shouldBe 0 - syncTracker.maxHeight() shouldBe None - - // clearStatus() is ok when there's no peer - syncTracker.clearStatus(connectedPeer) - syncTracker.getStatus(connectedPeer) shouldBe None - syncTracker.maxHeight() shouldBe None - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/FixedSizeApproximateCacheQueueSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/network/FixedSizeApproximateCacheQueueSpec.scala deleted file mode 100644 index de06f3d9c7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/FixedSizeApproximateCacheQueueSpec.scala +++ /dev/null @@ -1,51 +0,0 @@ -package org.ergoplatform.network - -import org.ergoplatform.network.FixedSizeApproximateCacheQueue.{ApproxCache, ConciseCache, elemCountApproxThreshold} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class FixedSizeApproximateCacheQueueSpec extends AnyFlatSpec with Matchers { - - it should "create fixed size amount of caches" in { - val queue = FixedSizeApproximateCacheQueue.empty(cacheQueueSize = 5) - val queue1 = - queue - .putAll((1 to 100).map(_.toString)) - .putAll((101 to 200).map(_.toString)) - .putAll((201 to 300).map(_.toString)) - - (1 to 300).foreach { n => - assert(queue1.mightContain(n.toString), s"$n should be in cache") - } - - queue1.cacheQueue.size shouldBe 3 - - val queue2 = - queue1 - .putAll(Vector("301")) - .putAll(Vector("302")) - .putAll(Vector("303")) - .putAll(Vector("304")) - .putAll(Vector("305")) - queue2.cacheQueue.size shouldBe 5 - - (301 to 305).foreach { n => - assert(queue2.mightContain(n.toString), s"$n should be in cache") - } - } - - it should "create different types of caches based on reaching approx threshold" in { - val queue = FixedSizeApproximateCacheQueue.empty(cacheQueueSize = 2) - - val fewElemQueue = queue.putAll((1 to 10).map(_.toString)) - assert(fewElemQueue.cacheQueue.head.isInstanceOf[ConciseCache], "Few elements should go to concise cache") - - val manyElemQueue = queue.putAll((1 to (elemCountApproxThreshold + 10)).map(_.toString)) - assert(manyElemQueue.cacheQueue.head.isInstanceOf[ApproxCache], "Many elements should go to approximate cache") - - val combinedQueue = manyElemQueue.putAll((1 to 10).map(_.toString)) - assert(combinedQueue.cacheQueue.head.isInstanceOf[ConciseCache], "Few elements should go to concise cache") - assert(combinedQueue.cacheQueue.last.isInstanceOf[ApproxCache], "Many elements should go to approximate cache") - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala deleted file mode 100644 index b00ec2867d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/HandshakeSpecification.scala +++ /dev/null @@ -1,97 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.app.Version -import scorex.core.network.message.HandshakeSerializer -import scorex.util.encode.Base16 - -class HandshakeSpecification extends ErgoPropertyTest with DecodingUtils { - - property("handshake test vectors") { - // bytes got from a real node - val hsBase16 = "bcd2919cee2e076572676f726566030306126572676f2d6d61696e6e65742d332e332e36000210040001000102067f000001ae46" - val hsBytes = Base16.decode(hsBase16).get - - val agentName = "ergoref" - - val peerName = "ergo-mainnet-3.3.6" - - val handshakeSerializer0 = HandshakeSerializer - val hs0 = handshakeSerializer0.parseBytes(hsBytes) - hs0.time shouldBe 1610134874428L // Friday, 8 January 2021, 19:41:14 - hs0.peerSpec.protocolVersion shouldBe Version(3, 3, 6) - hs0.peerSpec.agentName shouldBe agentName - hs0.peerSpec.nodeName shouldBe peerName - - val handshakeSerializer1 = HandshakeSerializer - val hs1 = handshakeSerializer1.parseBytes(hsBytes) - hs1.time shouldBe 1610134874428L - val mf = hs1.peerSpec.features.find(_.isInstanceOf[ModePeerFeature]).head.asInstanceOf[ModePeerFeature] - mf.stateType shouldBe StateType.Utxo - - // Byte-by-byte parsing below, according to the spec https://github.com/ergoplatform/ergo/wiki/P2P-Handshaking - - val bb = ByteBuffer.wrap(hsBytes) - val time = getULong(bb) - time shouldBe 1610134874428L - - val agentNameLength = getUByte(bb) - agentNameLength shouldBe agentName.length - - val agentNameParsed = getBytes(bb, agentNameLength) - new String(agentNameParsed, "UTF-8") shouldBe agentName - - val version = getBytes(bb, 3) - version(0) shouldBe 3 - version(1) shouldBe 3 - version(2) shouldBe 6 - - val peerNameLength = getUByte(bb) - peerNameLength shouldBe peerName.length - - val peerNameParsed = getBytes(bb, peerNameLength) - new String(peerNameParsed, "UTF-8") shouldBe peerName - - val pubNode = getUByte(bb) - - pubNode shouldBe 0 - - val featuresCount = getUByte(bb) - - featuresCount shouldBe 2 - - val firstFeatureId = getUByte(bb) - - firstFeatureId shouldBe 16 //mode feature - - val firstFeatureLength = getULong(bb) //should read one byte only - - firstFeatureLength shouldBe 4 - - val stateTypeCode = getUByte(bb).toByte - - val stateType = StateType.fromCode(stateTypeCode) - - stateType shouldBe StateType.Utxo - - val verifyTransactions = getUByte(bb).toByte - - verifyTransactions shouldBe 1 // true - - val nipopowSuffixLength = getUByte(bb).toByte - - nipopowSuffixLength shouldBe 0 // no nipopow suffix, the peer has full header-chain - - val blocksToKeep = getInt(bb) - - blocksToKeep shouldBe -1 // all the full blocks stored - - val secondFeatureId = getUByte(bb) - - secondFeatureId shouldBe 2 // local address feature id - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala deleted file mode 100644 index 8270804c48..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/HeaderSerializationSpecification.scala +++ /dev/null @@ -1,205 +0,0 @@ -package org.ergoplatform.network - -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.mining.{AutolykosSolution, groupElemFromBytes} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.crypto.authds.ADDigest -import scorex.crypto.hash.{Blake2b256, Digest32} -import scorex.util.ModifierId -import scorex.util.encode.Base16 -import sigmastate.crypto.CryptoConstants.EcPointType - -import java.nio.ByteBuffer - -class HeaderSerializationSpecification extends ErgoPropertyTest with DecodingUtils { - - private def base16ToEcPoint(pointEncoded: String): EcPointType = { - val bytes = Algos.decode(pointEncoded).get - groupElemFromBytes(bytes) - } - - // This test contains simple parser for header version 1 - // In Ergo mainnet, used for blocks till 417,791 - property("Header simple parsing - block version 1") { - // real header from mainnet, at 414,474, https://explorer.ergoplatform.com/en/blocks/8cf6dca6b9505243e36192fa107735024c0000cf4594b1daa2dc4e13ee86f26f - val version = 1 : Byte - val height = 414474 - val parentId = ModifierId @@ "8bdd043dab20aa690afc9a18fc4797de4f02f049f5c16f9657646c753d69582e" - val adProofsRoot = Digest32 @@ Base16.decode("4527a2a7bcee7f77b5697f505e5effc5342750f58a52dddfe407a3ce3bd3abd0").get - val stateRoot = ADDigest @@ Base16.decode("6c06d6277d40aeb958c5631515dc3ec3d11d8504e62de77df024d0ca67242fb512").get - val transactionsRoot = Digest32 @@ Base16.decode("722f9306300d0d96fe8c10de830216d700131614f9e6ce2496e8dba1cbb45951").get - val timestamp = 1611874199636L - val nBits = 118039443L - val extensionRoot = Digest32 @@ Base16.decode("a1a3933312467ce53d41fdc20e38c603e8fd89999371c60d7537c5d5760ef7c4").get - - val pk = base16ToEcPoint("02bb8eb301ab3d5d14515e33760d0dfb4f7191312a640db64a3a1aeeac9703f2d3") - val w = base16ToEcPoint("026d7b267c33120d15c267664081a6b77a6dcae6b35147db2c3e1195573119cb14") - val n = Base16.decode("0008a1d103880117").get - val d = BigInt("35863003992655055679291741607273543535646500642591973829915050") - val powSolution = AutolykosSolution(pk, w, n, d) - val votes = Array[Byte](4, 3, 0) - - val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) - - h.id shouldBe "8cf6dca6b9505243e36192fa107735024c0000cf4594b1daa2dc4e13ee86f26f" - - h.id shouldBe Base16.encode(Blake2b256(h.bytes)) // header id is blake2b256 of its bytes - - - //test vector - Base16.encode(h.bytes) shouldBe - "018bdd043dab20aa690afc9a18fc4797de4f02f049f5c16f9657646c753d69582e4527a2a7bcee7f77b5697f505e5effc5342750f58a52dddfe407a3ce3bd3abd0722f9306300d0d96fe8c10de830216d700131614f9e6ce2496e8dba1cbb459516c06d6277d40aeb958c5631515dc3ec3d11d8504e62de77df024d0ca67242fb512d4d0c1d9f42ea1a3933312467ce53d41fdc20e38c603e8fd89999371c60d7537c5d5760ef7c4070923938aa61904030002bb8eb301ab3d5d14515e33760d0dfb4f7191312a640db64a3a1aeeac9703f2d3026d7b267c33120d15c267664081a6b77a6dcae6b35147db2c3e1195573119cb140008a1d1038801171a16514e604d76c516eec4124f4066e6e326b9e8d2fc5165b631aa" - - h.bytes.length shouldBe 279 - - val bb = ByteBuffer.wrap(h.bytes) - - // read block version, 1 byte - val versionParsed = getByte(bb) - versionParsed shouldBe version - - // read parent header id, 32 bytes - val parentIdParsed = getBytes(bb, 32) - Base16.encode(parentIdParsed) shouldBe parentId - - // read authenticating hash of state transformation correctness proofs, 32 bytes - val adProofsRootParsed = getBytes(bb, 32) - adProofsRootParsed.toIndexedSeq shouldBe adProofsRoot.toIndexedSeq - - // read transactions Merkle tree root, 32 bytes - val transactionsRootParsed = getBytes(bb, 32) - transactionsRootParsed.toIndexedSeq shouldBe transactionsRoot.toIndexedSeq - - // read UTXO state AVL+ tree root + height, 33 bytes - val stateRootParsed = getBytes(bb, 33) - stateRootParsed.toIndexedSeq shouldBe stateRoot.toIndexedSeq - - val timestampParsed = getULong(bb) // timestamp, up to 8 bytes - timestampParsed shouldBe timestamp - - // read Merkle tree root of block extension data, 32 bytes - val extensionRootParsed = getBytes(bb, 32) - extensionRootParsed.toIndexedSeq shouldBe extensionRoot.toIndexedSeq - - // read difficulty encoded in Bitcoin nBits format, https://bitco.in/en/developer-reference#target-nbits - val nbits = getBytes(bb, 4) // 4 bytes - val difficulty = DifficultySerializer.decodeCompactBits(DifficultySerializer.readUint32BE(nbits)) - difficulty shouldBe h.requiredDifficulty - - val heightParsed = getULong(bb) // up to 4 bytes - heightParsed shouldBe height - - // read miner votes for protocol parameters update - val votesParsed = getBytes(bb, 3) - votesParsed.toIndexedSeq shouldBe votes.toIndexedSeq - - // read PoW solution - // read public key, 33 bytes (EC point) - val pkParsed = getBytes(bb, 33) - groupElemFromBytes(pkParsed) shouldBe pk - - // read one-time secret w, 33 bytes (EC point) - val wParsed = getBytes(bb, 33) - groupElemFromBytes(wParsed) shouldBe w - - // read nonce (8 bytes) - val nonceParsed = getBytes(bb, 8) - nonceParsed.toIndexedSeq shouldBe n.toIndexedSeq - - // read length of d, 1 byte - val dLength = getUByte(bb) - // read d bigint bytes - val dBytes = getBytes(bb, dLength) - val dParsed = BigInt(1, dBytes) - dParsed shouldBe d - } - - - // This test contains simple parser for header version 2 - // In Ergo mainnet, used for blocks since 417,792 (inclusive) - property("Header simple parsing - block version 2") { - // real header from mainnet, at 418,838, https://explorer.ergoplatform.com/en/blocks/f46c89e44f13a92d8409341490f97f05c85785fa8d2d2164332cc066eda95c39 - val version = 2 : Byte - val height = 418138 - val parentId = ModifierId @@ "7fbc70ec5913706ddef67bbcdb7700ea5f15dc709012491269c9c7eb545d720c" - val adProofsRoot = Digest32 @@ Base16.decode("a80bbd4d69b4f017da6dd9250448ef1cde492121fc350727e755c7b7ae2988ad").get - val stateRoot = ADDigest @@ Base16.decode("995c0efe63744c5227e6ae213a2061c60f8db845d47707a6bff53f9ff1936a9e13").get - val transactionsRoot = Digest32 @@ Base16.decode("141bf3de015c44995858a435e4d6c50c51622d077760de32977ba5412aaaae03").get - val timestamp = 1612465607426L - val nBits = 107976917L - val extensionRoot = Digest32 @@ Base16.decode("b1457df896bba9dc962f8e42187e1ac580842f1282c8c7fb9cf9f4cd520d1c07").get - - val pk = base16ToEcPoint("0315345f1fca9445eee5df74759d4c495094bcfc82a2831b26fca6efa599b509de") - val w = AutolykosSolution.wForV2 - val n = Base16.decode("1b95db2168f95fda").get - val d = AutolykosSolution.dForV2 - val powSolution = AutolykosSolution(pk, w, n, d) - val votes = Array[Byte](0, 0, 0) - - val h = Header(version, parentId, adProofsRoot, stateRoot, transactionsRoot, timestamp, nBits, - height, extensionRoot, powSolution, votes) - - h.id shouldBe "f46c89e44f13a92d8409341490f97f05c85785fa8d2d2164332cc066eda95c39" - - h.id shouldBe Base16.encode(Blake2b256(h.bytes)) // header id is blake2b256 of its bytes - - val bb = ByteBuffer.wrap(h.bytes) - - // read block version - val versionParsed = getByte(bb) - versionParsed shouldBe version - - // read parent id, 32 bytes - val parentIdParsed = getBytes(bb, 32) - Base16.encode(parentIdParsed) shouldBe parentId - - // read authenticating hash of state transformation correctness proofs, 32 bytes - val adProofsRootParsed = getBytes(bb, 32) - adProofsRootParsed.toIndexedSeq shouldBe adProofsRoot.toIndexedSeq - - // read transactions Merkle tree root, 32 bytes - val transactionsRootParsed = getBytes(bb, 32) - transactionsRootParsed.toIndexedSeq shouldBe transactionsRoot.toIndexedSeq - - // read UTXO state AVL+ tree root + height, 33 bytes - val stateRootParsed = getBytes(bb, 33) - stateRootParsed.toIndexedSeq shouldBe stateRoot.toIndexedSeq - - val timestampParsed = getULong(bb) // timestamp, up to 8 bytes - timestampParsed shouldBe timestamp - - // read Merkle tree root of block extension data, 32 bytes - val extensionRootParsed = getBytes(bb, 32) - extensionRootParsed.toIndexedSeq shouldBe extensionRoot.toIndexedSeq - - // read difficulty encoded in Bitcoin nBits format, https://bitco.in/en/developer-reference#target-nbits - val nbits = getBytes(bb, 4) // 4 bytes - val difficulty = DifficultySerializer.decodeCompactBits(DifficultySerializer.readUint32BE(nbits)) - difficulty shouldBe h.requiredDifficulty - - val heightParsed = getULong(bb) // up to 4 bytes - heightParsed shouldBe height - - // read miner votes for protocol parameters update - val votesParsed = getBytes(bb, 3) - votesParsed.toIndexedSeq shouldBe votes.toIndexedSeq - - // Block version V2 specific field, contains length of additional data - val additionalFieldsLength = getUByte(bb) - additionalFieldsLength shouldBe 0 - - // read PoW solution, no "w" and "d" in block version 2 - - val pkParsed = getBytes(bb, 33) - groupElemFromBytes(pkParsed) shouldBe pk - - val nonceParsed = getBytes(bb, 8) - nonceParsed.toIndexedSeq shouldBe n.toIndexedSeq - - bb.remaining() shouldBe 0 - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/InvSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/InvSpecification.scala deleted file mode 100644 index 7c756ec079..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/InvSpecification.scala +++ /dev/null @@ -1,76 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -import com.google.common.primitives.Ints -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.message.{InvData, InvSpec, Message, MessageSerializer} -import scorex.crypto.hash -import scorex.util.ModifierId -import scorex.util.encode.Base16 - -/** - * Inv message is informing peers around about transactions and block parts available - */ -class InvSpecification extends ErgoPropertyTest with DecodingUtils { - - property("inv reference parser") { - val magic = Array(1: Byte, 0: Byte, 2: Byte, 4: Byte) // mainnet magic - val invSpec = InvSpec - - val headerId = Array.fill(16)(1: Byte) ++ Array.fill(16)(2: Byte) - - val headerIdEncoded = ModifierId @@ Base16.encode(headerId) - - val invData = InvData(Header.modifierTypeId, Seq(headerIdEncoded)) - - val invMessage = Message(invSpec, Right(invData), None) - - val ms = new MessageSerializer(Seq(invSpec), magic) - - val bs = ms.serialize(invMessage).toArray - val bsString = Base16.encode(bs) - - // test vector for external implementations - bsString shouldBe "0100020437000000226abfdbf565010101010101010101010101010101010102020202020202020202020202020202" - - val bb = ByteBuffer.wrap(bs) - - // simple reference parser below - - // read network magic (network id) bytes (4 bytes) - val magicRead = getBytes(bb, 4) - magicRead.toIndexedSeq shouldBe magic.toIndexedSeq - - // read message type id - val messageCode = getByte(bb) - messageCode shouldBe invSpec.messageCode // 55 (in dec) - - // read message length (4 bytes) - val messageLength = Ints.fromByteArray(getBytes(bb,4)) - - messageLength shouldBe 34 - - val checkSum = getBytes(bb, 4) - - // read modifier type id (1 byte) - val modifierTypeId = getByte(bb) // should read one byte only - - modifierTypeId shouldBe 101.toByte // type id corresponding to block header - - // read number of modifiers (headers) - val headersCount = getULong(bb).toInt // should read up to 4 bytes max - - headersCount shouldBe 1 - - // read mofifier (header) ids - val headerIdParsed = getBytes(bb, 32) - - headerIdParsed.toIndexedSeq shouldBe headerId.toIndexedSeq - - // validating checksum - checkSum shouldBe hash.Blake2b256(Array(modifierTypeId, headersCount.toByte) ++ headerId).take(4) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ModePeerFeatureSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ModePeerFeatureSpecification.scala deleted file mode 100644 index 092a1ad45d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ModePeerFeatureSpecification.scala +++ /dev/null @@ -1,25 +0,0 @@ -package org.ergoplatform.network - -import org.ergoplatform.utils.ErgoPropertyTest -import scala.util.Try - - -class ModePeerFeatureSpecification extends ErgoPropertyTest { - - //roundtrip test is provided in SerializationTests - - property("additional bytes can be added") { - forAll(modeFeatureGen) { mf => - val bs = mf.serializer.toBytes(mf) - mf.serializer.parseBytes(bs ++ Array(1: Byte, 2: Byte, 3: Byte)) shouldEqual mf - } - } - - property("serialization of too big byte array fails") { - forAll(modeFeatureGen) { mf => - val bs = mf.serializer.toBytes(mf) - Try(mf.serializer.parseBytes(bs ++ Array.fill(512)(0: Byte))).isFailure shouldBe true - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala deleted file mode 100644 index bc8e8d876f..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/ModifiersSpecification.scala +++ /dev/null @@ -1,78 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -import com.google.common.primitives.Ints -import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.message.{Message, MessageSerializer, ModifiersData, ModifiersSpec} -import scorex.util.encode.Base16 - -/** - * Modifiers message used to send transactions or block parts to a remote peer - */ -class ModifiersSpecification extends ErgoPropertyTest with DecodingUtils { - - property("modifiers message reference parser") { - val hBytes = Base16.decode("4201ad7fffba807080ce7f808001b4771880bdffbd7fff857f8db17fdc89b0015bff0189486d80934a84015e03c064c6d100c17fae55bf01f380007fbb00ff01d9000000013f0680d10015ff11c4b7ffff01ffb2d27f0001050064010080ffb93e7fff4cc15a2bffdd770480007f8080ff8026802f7f51007f004b01ff0080002380a581e8c0ca81dfca62007fa7ff01860019f37f3c4491067cd1001ee07e570fe8689b80ff11017aff7408703927a2bbc4fa0200000000032bdb4c610ddf0078b4f31f5a36bff7b003704dfc93b201fedd8fe331d9ff1102008d7fff010d80ff").get - val header = HeaderSerializer.parseBytes(hBytes) - - val magic = Array(1: Byte, 0: Byte, 2: Byte, 4: Byte) // mainnet magic - val mSpec = ModifiersSpec - - val mData = ModifiersData(Header.modifierTypeId, Map(header.id -> header.bytes)) - - val mMessage = Message(mSpec, Right(mData), None) - - val ms = new MessageSerializer(Seq(mSpec), magic) - - val bs = ms.serialize(mMessage).toArray - val bsString = Base16.encode(bs) - - // test vector for external implementations - bsString shouldBe "0100020421000001058fdd57ca65010d537f94ae67e5026fd4acee1cdd1e7281a73e94a7681864438c629e9683b3a5e1014201ad7fffba807080ce7f808001b4771880bdffbd7fff857f8db17fdc89b0015bff0189486d80934a84015e03c064c6d100c17fae55bf01f380007fbb00ff01d9000000013f0680d10015ff11c4b7ffff01ffb2d27f0001050064010080ffb93e7fff4cc15a2bffdd770480007f8080ff8026802f7f51007f004b01ff0080002380a581e8c0ca81dfca62007fa7ff01860019f37f3c4491067cd1001ee07e570fe8689b80ff11017aff7408703927a2bbc4fa0200000000032bdb4c610ddf0078b4f31f5a36bff7b003704dfc93b201fedd8fe331d9ff1102008d7fff010d80ff" - - val bb = ByteBuffer.wrap(bs) - - // simple reference parser below - - // read network magic (network id) bytes (4 bytes) - val magicRead = getBytes(bb, 4) - magicRead.toIndexedSeq shouldBe magic.toIndexedSeq - - // read message type id - val messageCode = getByte(bb) - messageCode shouldBe mSpec.messageCode // 33 (in dec) - - // read message length (4 bytes) - val messageLength = Ints.fromByteArray(getBytes(bb,4)) - - messageLength shouldBe 261 - - getBytes(bb, 4) - - // read modifier type id (1 byte) - val modifierTypeId = getByte(bb) // should read one byte only - - modifierTypeId shouldBe 101.toByte // type id corresponding to block header - - // read number of modifiers (headers) - val headersCount = getULong(bb).toInt // could read up to 4 bytes max - - headersCount shouldBe 1 - - // read modifier (header) id - val headerIdParsed = getBytes(bb, 32) - - Base16.encode(headerIdParsed) shouldBe header.id - - // read read modifier (header) bytes length - val headerLength = getULong(bb).toInt // could read up to 4 bytes max - - // read read modifier (header) bytes - val headerBytes = getBytes(bb, headerLength) - - headerBytes.toIndexedSeq shouldBe header.bytes.toIndexedSeq - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala deleted file mode 100644 index cd7ee1e71e..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/PeerFilteringRuleSpecification.scala +++ /dev/null @@ -1,56 +0,0 @@ -package org.ergoplatform.network - -import akka.actor.ActorRef -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.app.Version -import scorex.core.network.PeerSpec -import scorex.core.network.peer.PeerInfo -import scorex.core.network.{ConnectedPeer, ConnectionId} - -class PeerFilteringRuleSpecification extends ErgoPropertyTest { - - private def peerWithVersion(version: Version): ConnectedPeer = { - val ref = ActorRef.noSender - val peerSpec = PeerSpec("", version, "", None, Seq.empty) - val peerInfo = PeerInfo(peerSpec, lastHandshake = 0L, None, 0L) - ConnectedPeer(ConnectionId(null, null, null), ref, Some(peerInfo)) - } - - property("syncv2 filter") { - val v1Peer = peerWithVersion(Version(4, 0, 15)) - val v2Peer0 = peerWithVersion(Version(4, 0, 16)) - val v2Peer1 = peerWithVersion(Version(4, 0, 21)) - val v2Peer2 = peerWithVersion(Version(5, 0, 0)) - - SyncV2Filter.filter(Seq(v1Peer, v2Peer0, v2Peer1, v2Peer2)) shouldBe Seq(v2Peer0, v2Peer1, v2Peer2) - } - - property("utxo set snapshot filter") { - val peer0 = peerWithVersion(Version(4, 0, 17)) - val peer1 = peerWithVersion(Version(4, 0, 18)) - val peer2 = peerWithVersion(Version(4, 0, 16)) - val peer3 = peerWithVersion(Version(4, 0, 19)) - val peer4 = peerWithVersion(Version(5, 0, 0)) - val peer5 = peerWithVersion(Version(5, 0, 5)) - val peer6 = peerWithVersion(Version(5, 0, 15)) - val peer7 = peerWithVersion(Version(5, 0, 25)) - - UtxoSetNetworkingFilter.filter(Seq(peer0, peer1, peer2, peer3, peer4, peer5, peer6, peer7)) shouldBe - Seq(peer6, peer7) - } - - property("nipopow support filter") { - val peer0 = peerWithVersion(Version(4, 0, 17)) - val peer1 = peerWithVersion(Version(4, 0, 18)) - val peer2 = peerWithVersion(Version(4, 0, 16)) - val peer3 = peerWithVersion(Version(4, 0, 19)) - val peer4 = peerWithVersion(Version(5, 0, 0)) - val peer5 = peerWithVersion(Version(5, 0, 12)) - val peer6 = peerWithVersion(Version(5, 0, 13)) - val peer7 = peerWithVersion(Version(5, 0, 25)) - - NipopowSupportFilter.filter(Seq(peer0, peer1, peer2, peer3, peer4, peer5, peer6, peer7)) shouldBe - Seq(peer6, peer7) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala deleted file mode 100644 index 7489c43871..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/network/RequestModifiersSpecification.scala +++ /dev/null @@ -1,77 +0,0 @@ -package org.ergoplatform.network - -import java.nio.ByteBuffer - -import com.google.common.primitives.Ints -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.message.{InvData, Message, MessageSerializer, RequestModifierSpec} -import scorex.crypto.hash -import scorex.util.ModifierId -import scorex.util.encode.Base16 - -/** - * RequestModifiers message is used to ask peers about transactions and block parts to download - */ -class RequestModifiersSpecification extends ErgoPropertyTest with DecodingUtils { - - property("requestModifiers reference parser") { - - val magic = Array(1: Byte, 0: Byte, 2: Byte, 4: Byte) // mainnet magic - val rmSpec = RequestModifierSpec - - val headerId = Array.fill(16)(1: Byte) ++ Array.fill(16)(2: Byte) - - val headerIdEncoded = ModifierId @@ Base16.encode(headerId) - - val invData = InvData(Header.modifierTypeId, Seq(headerIdEncoded)) - - val rmMessage = Message(rmSpec, Right(invData), None) - - val ms = new MessageSerializer(Seq(rmSpec), magic) - - val bs = ms.serialize(rmMessage).toArray - val bsString = Base16.encode(bs) - - // test vector for external implementations - bsString shouldBe "0100020416000000226abfdbf565010101010101010101010101010101010102020202020202020202020202020202" - - val bb = ByteBuffer.wrap(bs) - - // simple reference parser below - - // read network magic (network id) bytes (4 bytes) - val magicRead = getBytes(bb, 4) - magicRead.toIndexedSeq shouldBe magic.toIndexedSeq - - // read message type id - val messageCode = getByte(bb) - messageCode shouldBe rmSpec.messageCode // 22 (in dec) - - // read message length (4 bytes) - val messageLength = Ints.fromByteArray(getBytes(bb,4)) - - messageLength shouldBe 34 - - val checkSum = getBytes(bb, 4) - - // read modifier type id (1 byte) - val modifierTypeId = getByte(bb) // should read one byte only - - modifierTypeId shouldBe 101.toByte // type id corresponding to block header - - // read number of modifiers (headers) - val headersCount = getULong(bb).toInt // should read up to 4 bytes max - - headersCount shouldBe 1 - - // read modifier (header) ids - val headerIdParsed = getBytes(bb, 32) - - headerIdParsed.toIndexedSeq shouldBe headerId.toIndexedSeq - - // validating checksum - checkSum shouldBe hash.Blake2b256(Array(modifierTypeId, headersCount.toByte) ++ headerId).take(4) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala deleted file mode 100644 index 29e67176bd..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala +++ /dev/null @@ -1,119 +0,0 @@ -package org.ergoplatform.nodeView - -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers} -import scorex.crypto.hash.Blake2b256 -import scorex.util.{ModifierId, bytesToId} - -import scala.annotation.tailrec - -class ErgoModifiersCacheSpec extends ErgoPropertyTest with HistoryTestHelpers { - - private def genKey(i: Int): ModifierId = bytesToId(Blake2b256(s"$i")) - - private def genCachePair(i: Int): (ModifierId, Header) = { - val header = defaultHeaderGen.sample.value - val k = genKey(i) - k -> header - } - - property("cache size is within limits") { - val limit = 3 - val modifiersCache = new ErgoModifiersCache(limit) - - modifiersCache.maxSize shouldBe limit - - (1 to limit).foreach { i => - val (k, h) = genCachePair(i) - modifiersCache.put(k, h) - } - - modifiersCache.size shouldBe limit - - val above = genCachePair(limit + 1) - - modifiersCache.put(above._1, above._2) - modifiersCache.size shouldBe (limit + 1) - - modifiersCache.cleanOverfull() - - modifiersCache.size shouldBe limit - - modifiersCache.remove(genKey(1)).isEmpty shouldBe true - } - - property("cache is proposing a reasonable candidate to enhance history") { - val limit = 25 - val modifiersCache = new ErgoModifiersCache(limit) - - val history0 = generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, BlocksToKeep) - - val chain = genChain(5, history0) - - chain.foreach { fb => - modifiersCache.put(fb.header.id, fb.header) - modifiersCache.put(fb.header.transactionsId, fb.blockTransactions) - modifiersCache.put(fb.header.ADProofsId, fb.adProofs.value) - } - - //The history is empty - we can apply only a header at height == 0 at this moment. - //Out of 15 elements in the cache, the cache should propose a proper candidate - val c1 = modifiersCache.popCandidate(history0).value - c1.isInstanceOf[Header] shouldBe true - val h1 = c1.asInstanceOf[Header] - h1.height shouldBe ErgoHistory.GenesisHeight - - val history1 = history0.append(c1).get._1 - - //We have only header of height == 0 in the history, so cache should return whether a header of height == 1 - //or a non-header part of the full block at height == 0 - val c2 = modifiersCache.popCandidate(history1).value - val properCandidate = c2 match { - case h: Header => h.height == 1 - case bt: BlockTransactions => bt.id == h1.transactionsId - case ap: ADProofs => ap.id == h1.ADProofsId - } - properCandidate shouldBe true - } - - property("cache is proposing proper candidate during forking") { - val limit = 25 - val modifiersCache = new ErgoModifiersCache(limit) - - var history = generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, BlocksToKeep) - - val chain = genChain(1, history) - - chain.foreach{fb => history = applyBlock(history, fb)} - - val chain1 = genChain(5, history).tail - - val chain2 = genChain(10, history).tail - - chain1.foreach(fb => history = applyBlock(history, fb)) - - chain2.foreach(fb => history = history.append(fb.header).get._1) - - history.bestFullBlockOpt.value shouldBe chain1.last - history.bestHeaderOpt.value shouldBe chain2.last.header - - chain2.flatMap(_.blockSections).foreach(s => modifiersCache.put(s.id, s)) - - @tailrec - def applyLoop(): Unit = { - modifiersCache.popCandidate(history) match { - case Some(mod) => - history.append(mod) - applyLoop() - case None => - modifiersCache.size shouldBe 0 - history.bestFullBlockOpt.value shouldBe chain2.last - } - } - applyLoop() - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala deleted file mode 100644 index 9311d13c78..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala +++ /dev/null @@ -1,366 +0,0 @@ -package org.ergoplatform.nodeView - -import akka.actor.{ActorRef, ActorSystem} -import akka.testkit.TestProbe -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetNodeViewChanges, ModifiersFromRemote} -import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoSyncInfo, ErgoSyncInfoMessageSpec} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.UtxoState.ManifestId -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.settings.Algos -import org.ergoplatform.wallet.utils.TestFileUtils -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import scorex.core.consensus.SyncInfo -import scorex.core.network.ConnectedPeer -import scorex.core.network.NetworkController.ReceivableMessages.{PenalizePeer, SendToNetwork} -import scorex.core.network.message._ -import scorex.core.network.peer.PenaltyType -import scorex.core.serialization.{BytesSerializable, ErgoSerializer, ManifestSerializer} -import scorex.crypto.hash.Digest32 -import scorex.testkit.generators.{SyntacticallyTargetedModifierProducer, TotallyValidModifierProducer} -import scorex.testkit.utils.AkkaFixture -import scorex.util.ScorexLogging -import scorex.util.serialization.{Reader, Writer} -import org.ergoplatform.utils.generators.ChainGenerator - -import scala.concurrent.Await -import scala.concurrent.duration._ -import scala.language.postfixOps -import scala.util.Random - -@SuppressWarnings(Array("org.wartremover.warts.IsInstanceOf")) -trait NodeViewSynchronizerTests[ST <: ErgoState[ST]] extends AnyPropSpec - with Matchers - with ScorexLogging - with SyntacticallyTargetedModifierProducer - with TotallyValidModifierProducer[ST] - with ChainGenerator - with TestFileUtils { - - implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global - - val historyGen: Gen[ErgoHistory] - val memPool: ErgoMemPool - - val stateGen: Gen[ST] - - def nodeViewSynchronizer(implicit system: ActorSystem): - (ActorRef, ErgoSyncInfo, BlockSection, ErgoTransaction, ConnectedPeer, TestProbe, TestProbe, TestProbe, TestProbe, ErgoSerializer[BlockSection]) - - class SynchronizerFixture extends AkkaFixture { - @SuppressWarnings(Array("org.wartremover.warts.PublicInference")) - val (node, syncInfo, mod, tx, peer, pchProbe, ncProbe, vhProbe, eventListener, modSerializer) = nodeViewSynchronizer - } - - // ToDo: factor this out of here and NVHTests? - private def withFixture(testCode: SynchronizerFixture => Any): Unit = { - val fixture = new SynchronizerFixture - try { - testCode(fixture) - } - finally { - Await.result(fixture.system.terminate(), Duration.Inf) - } - } - - property("NodeViewSynchronizer: SuccessfulTransaction") { - withFixture { ctx => - import ctx._ - node ! SuccessfulTransaction(UnconfirmedTransaction(tx, None)) - ncProbe.fishForMessage(3 seconds) { case m => m.isInstanceOf[SendToNetwork] } - } - } - - property("NodeViewSynchronizer: FailedTransaction") { - withFixture { ctx => - import ctx._ - node ! FailedTransaction(UnconfirmedTransaction(tx, None), new Exception) - // todo: NVS currently does nothing in this case. Should check banning. - } - } - - property("NodeViewSynchronizer: SyntacticallySuccessfulModifier") { - withFixture { ctx => - import ctx._ - node ! SyntacticallySuccessfulModifier(mod.modifierTypeId, mod.id) - // todo ? : NVS currently does nothing in this case. Should it do? - } - } - - property("NodeViewSynchronizer: SyntacticallyFailedModification") { - withFixture { ctx => - import ctx._ - node ! SyntacticallyFailedModification(mod.modifierTypeId, mod.id, new Exception) - // todo: NVS currently does nothing in this case. Should check banning. - } - } - - property("NodeViewSynchronizer: SemanticallySuccessfulModifier") { - withFixture { ctx => - import ctx._ - node ! FullBlockApplied(mod.asInstanceOf[Header]) //todo: fix - ncProbe.fishForMessage(3 seconds) { case m => m.isInstanceOf[SendToNetwork] } - } - } - - property("NodeViewSynchronizer: SemanticallyFailedModification") { - withFixture { ctx => - import ctx._ - node ! SemanticallyFailedModification(mod.modifierTypeId, mod.id, new Exception) - // todo: NVS currently does nothing in this case. Should check banning. - } - } - - //TODO rewrite - ignore("NodeViewSynchronizer: Message: SyncInfoSpec") { - withFixture { ctx => - import ctx._ - - val dummySyncInfoMessageSpec = new SyncInfoMessageSpec[SyncInfo](serializer = new ErgoSerializer[SyncInfo] { - override def parse(r: Reader): SyncInfo = { - throw new Exception() - } - - override def serialize(obj: SyncInfo, w: Writer): Unit = {} - }) - - val dummySyncInfo: SyncInfo = new SyncInfo { - type M = BytesSerializable - - def serializer: ErgoSerializer[M] = throw new Exception - } - - val msgBytes = dummySyncInfoMessageSpec.toBytes(dummySyncInfo) - - node ! Message(dummySyncInfoMessageSpec, Left(msgBytes), Some(peer)) - // vhProbe.fishForMessage(3 seconds) { case m => m == OtherNodeSyncingInfo(peer, dummySyncInfo) } - } - } - - property("NodeViewSynchronizer: GetNipopowProof") { - withFixture { ctx => - import ctx._ - - // Generate history chain - val emptyHistory = historyGen.sample.get - val prefix = blockStream(None).take(settings.chainSettings.makeSnapshotEvery) - val fullHistory = applyChain(emptyHistory, prefix) - - // Broadcast updated history - node ! ChangedHistory(fullHistory) - - // Build and send GetNipopowProofSpec request - val spec = GetNipopowProofSpec - val msgBytes = spec.toBytes(NipopowProofData(m = emptyHistory.P2PNipopowProofM, k = emptyHistory.P2PNipopowProofK, headerId = None)) - node ! Message[NipopowProofData](spec, Left(msgBytes), Option(peer)) - - // Listen for NipopowProofSpec response - ncProbe.fishForMessage(5 seconds) { - case stn: SendToNetwork => - stn.message.spec match { - case _: NipopowProofSpec.type => true - case _ => false - } - case _: Any => false - } - } - } - - property("NodeViewSynchronizer: Message: InvSpec") { - withFixture { ctx => - import ctx._ - val syncMsgBytes = ErgoSyncInfoMessageSpec.toBytes(syncInfo) - node ! Message(ErgoSyncInfoMessageSpec, Left(syncMsgBytes), Some(peer)) - - val spec = InvSpec - val modifiers = Seq(mod.id) - val msgBytes = spec.toBytes(InvData(mod.modifierTypeId, modifiers)) - node ! Message(spec, Left(msgBytes), Some(peer)) - ncProbe.fishForMessage(5 seconds) { - case SendToNetwork(msg, _) - if msg.spec.messageCode == RequestModifierSpec.messageCode && - msg.data.get.asInstanceOf[InvData].ids.head == mod.id => true - case _ => false - } - } - } - - property("NodeViewSynchronizer: Message: RequestModifierSpec") { - withFixture { ctx => - import ctx._ - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val h = historyGen.sample.get - val mod = syntacticallyValidModifier(h) - val (newH, _) = h.append(mod).get - val m = memPool - val spec = RequestModifierSpec - val modifiers = Seq(mod.id) - val msgBytes = spec.toBytes(InvData(mod.modifierTypeId, modifiers)) - node ! ChangedHistory(newH) - node ! ChangedMempool(m) - node ! Message(spec, Left(msgBytes), Option(peer)) - - pchProbe.fishForMessage(5 seconds) { - case _: Message[_] => true - case _ => false - } - } - } - - property("NodeViewSynchronizer: Message: Non-Asked Modifiers from Remote") { - withFixture { ctx => - import ctx._ - - val modifiersSpec = ModifiersSpec - val msgBytes = modifiersSpec.toBytes(ModifiersData(mod.modifierTypeId, Map(mod.id -> mod.bytes))) - - node ! Message(modifiersSpec, Left(msgBytes), Option(peer)) - val messages = vhProbe.receiveWhile(max = 3 seconds, idle = 1 second) { case m => m } - assert(!messages.exists(_.isInstanceOf[ModifiersFromRemote])) - } - } - - property("NodeViewSynchronizer: Message: Asked Modifiers from Remote") { - withFixture { ctx => - import ctx._ - vhProbe.expectMsgType[GetNodeViewChanges] - - val invSpec = InvSpec - val invMsgBytes = invSpec.toBytes(InvData(mod.modifierTypeId, Seq(mod.id))) - - val modifiersSpec = ModifiersSpec - val modMsgBytes = modifiersSpec.toBytes(ModifiersData(mod.modifierTypeId, Map(mod.id -> mod.bytes))) - - node ! Message(invSpec, Left(invMsgBytes), Option(peer)) - node ! Message(modifiersSpec, Left(modMsgBytes), Option(peer)) - vhProbe.fishForMessage(3 seconds) { - case m: ModifiersFromRemote => m.modifiers.toSeq.contains(mod) - case _ => false - } - } - } - - property("NodeViewSynchronizer: Message - CheckDelivery - Do not penalize if delivered") { - withFixture { ctx => - import ctx._ - - val invSpec = InvSpec - val invMsgBytes = invSpec.toBytes(InvData(mod.modifierTypeId, Seq(mod.id))) - - val modifiersSpec = ModifiersSpec - val modMsgBytes = modifiersSpec.toBytes(ModifiersData(mod.modifierTypeId, Map(mod.id -> mod.bytes))) - - node ! Message(invSpec, Left(invMsgBytes), Option(peer)) - node ! Message(modifiersSpec, Left(modMsgBytes), Option(peer)) - system.scheduler.scheduleOnce(1 second, node, Message(modifiersSpec, Left(modMsgBytes), Option(peer))) - val messages = ncProbe.receiveWhile(max = 5 seconds, idle = 1 second) { case m => m } - assert(!messages.contains(PenalizePeer(peer.connectionId.remoteAddress, PenaltyType.MisbehaviorPenalty))) - } - } - - - property("NodeViewSynchronizer: GetSnapshotInfo") { - withFixture { ctx => - import ctx._ - - val s = stateGen.sample.get - - if (s.isInstanceOf[UtxoStateReader]) { - // To initialize utxoStateReaderOpt in ErgoNodeView Synchronizer - node ! ChangedState(s) - - // First, store snapshots info in DB - val m = (0 until 100).map { _ => - Random.nextInt(1000000) -> (Digest32 @@ Algos.decode(mod.id).get) - }.toMap - val si = new SnapshotsInfo(m) - val db = SnapshotsDb.create(createTempDir.getPath) - db.writeSnapshotsInfo(si) - - // Then send message to request it - node ! Message[Unit](GetSnapshotsInfoSpec, Left(Array.empty[Byte]), Option(peer)) - ncProbe.fishForMessage(5 seconds) { - case stn: SendToNetwork if stn.message.spec.isInstanceOf[SnapshotsInfoSpec.type] => true - case _: Any => false - } - } else { - log.info("Snapshots not supported by digest-state") - } - } - } - - property("NodeViewSynchronizer: GetManifest") { - withFixture { ctx => - import ctx._ - - val s = stateGen.sample.get - - s match { - case usr: UtxoState => { - // To initialize utxoStateReaderOpt in ErgoNodeView Synchronizer - node ! ChangedState(s) - - // Generate some snapshot - val height = 1 - usr.applyModifier(mod, Some(height))(_ => ()) - - val manifestId = usr.dumpSnapshot(height, usr.rootDigest.dropRight(1)).get - - // Then send message to request it - node ! Message[ManifestId](GetManifestSpec, Left(manifestId), Option(peer)) - ncProbe.fishForMessage(5 seconds) { - case stn: SendToNetwork if stn.message.spec.isInstanceOf[ManifestSpec.type] => true - case _: Any => false - } - } - case _ => - log.info("Snapshots not supported by digest-state") - } - } - } - - property("NodeViewSynchronizer: GetSnapshotChunk") { - withFixture { ctx => - import ctx._ - - val s = stateGen.sample.get - - s match { - case usr: UtxoState => { - // To initialize utxoStateReaderOpt in ErgoNodeView Synchronizer - node ! ChangedState(s) - - // Generate some snapshot - - val height = 1 - - usr.applyModifier(mod, Some(height))(_ => ()) - - val manifestDepth = 2.toByte - val serializer = new ManifestSerializer(manifestDepth) - usr.dumpSnapshot(height, usr.rootDigest.dropRight(1), manifestDepth) - val manifestId = usr.snapshotsDb.readSnapshotsInfo.availableManifests.apply(height) - val manifestBytes = usr.snapshotsDb.readManifestBytes(manifestId).get - val manifest = serializer.parseBytes(manifestBytes) - val subtreeIds = manifest.subtreesIds - - // Then send message to request it - node ! Message[ManifestId](GetUtxoSnapshotChunkSpec, Left(subtreeIds.last), Option(peer)) - ncProbe.fishForMessage(5 seconds) { - case stn: SendToNetwork if stn.message.spec.isInstanceOf[UtxoSnapshotChunkSpec.type] => true - case _: Any => false - } - } - case _ => - log.info("Snapshots not supported by digest-state") - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala deleted file mode 100644 index 40feb58cef..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala +++ /dev/null @@ -1,102 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.modifiers.{BlockSection, NonHeaderBlockSection} -import org.ergoplatform.modifiers.history._ -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.core.consensus.ModifierSemanticValidity -import scorex.crypto.hash.Blake2b256 -import scorex.util.ModifierId -import scorex.util.encode.Base16 - -class BlockSectionValidationSpecification extends HistoryTestHelpers { - - private def changeProofByte(version: Header.Version, outcome: Symbol) = { - val (history, block) = init(version) - val bt = block.blockTransactions - val txBytes = HistoryModifierSerializer.toBytes(bt) - - val txs = bt.transactions - val proof = txs.head.inputs.head.spendingProof.proof - proof(0) = if(proof.head < 0) (proof.head + 1).toByte else (proof.head - 1).toByte - - val txBytes2 = HistoryModifierSerializer.toBytes(bt) - - val hashBefore = Base16.encode(Blake2b256(txBytes)) - val hashAfter = Base16.encode(Blake2b256(txBytes2)) - - val wrongBt = HistoryModifierSerializer.parseBytes(txBytes2).asInstanceOf[BlockTransactions] - - hashBefore should not be hashAfter - history.applicableTry(bt) shouldBe 'success - history.applicableTry(wrongBt) shouldBe outcome - } - - property("BlockTransactions - proof byte changed - v.1") { - changeProofByte(Header.InitialVersion, outcome = 'success) - } - - property("BlockTransactions - proof byte changed - v.2") { - changeProofByte((Header.InitialVersion + 1).toByte, outcome = 'failure) - } - - property("BlockTransactions commons check") { - val (history, block) = init() - commonChecks(history, block.blockTransactions, block.header) - } - - property("ADProofs validation") { - val (history, block) = init() - commonChecks(history, block.adProofs.get, block.header) - } - - property("Extension validation") { - val (history, block) = init() - commonChecks(history, block.extension, block.header) - } - - private def init(version: Header.Version = Header.InitialVersion) = { - var history = genHistory() - val chain = genChain(2, history, version) - history = applyBlock(history, chain.head) - history = history.append(chain.last.header).get._1 - (history, chain.last) - } - - private def commonChecks(history: ErgoHistory, section: NonHeaderBlockSection, header: Header) = { - history.applicableTry(section) shouldBe 'success - // header should contain correct digest - history.applicableTry(withUpdatedHeaderId(section, section.id)) shouldBe 'failure - - // should not be able to apply when blocks at this height are already pruned - history.applicableTry(section) shouldBe 'success - history.writeMinimalFullBlockHeight(history.bestHeaderOpt.get.height + 1) - history.isHeadersChainSyncedVar = true - history.applicableTry(section) shouldBe 'failure - history.writeMinimalFullBlockHeight(ErgoHistory.GenesisHeight) - - // should not be able to apply if corresponding header is marked as invalid - history.applicableTry(section) shouldBe 'success - history.historyStorage.insert(Array(history.validityKey(header.id) -> Array(0.toByte)), Array.empty[BlockSection]).get - history.isSemanticallyValid(header.id) shouldBe ModifierSemanticValidity.Invalid - history.applicableTry(section) shouldBe 'failure - history.historyStorage.insert(Array(history.validityKey(header.id) -> Array(1.toByte)), Array.empty[BlockSection]).get - - // should not be able to apply if already in history - history.applicableTry(section) shouldBe 'success - history.append(section).get - history.applicableTry(section) shouldBe 'failure - } - - private def genHistory() = - generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, BlocksToKeep) - - private def withUpdatedHeaderId[T <: NonHeaderBlockSection](section: T, newId: ModifierId): T = section match { - case s: Extension => s.copy(headerId = newId).asInstanceOf[T] - case s: BlockTransactions => s.copy(headerId = newId).asInstanceOf[T] - case s: ADProofs => s.copy(headerId = newId).asInstanceOf[T] - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala deleted file mode 100644 index b2cbb964ca..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala +++ /dev/null @@ -1,303 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.modifiers.history.HeaderChain -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.crypto.hash.Digest32 -import scorex.core.consensus.{Older, Younger, Fork, Equal} - -import scala.util.Random - -class NonVerifyADHistorySpecification extends HistoryTestHelpers { - - private def genHistory() = - generateHistory(verifyTransactions = false, StateType.Digest, PoPoWBootstrap = false, blocksToKeep = 0, epochLength = 1000) - .ensuring(_.bestFullBlockOpt.isEmpty) - - private lazy val popowHistory = ensureMinimalHeight(genHistory(), 100) - - property("Should calculate difficulty correctly") { - val epochLength = 3 - val useLastEpochs = 3 - - val initDiff = BigInt(2) - val initDiffBits = DifficultySerializer.encodeCompactBits(initDiff) - - var history = generateHistory( - verifyTransactions = false, - StateType.Digest, - PoPoWBootstrap = false, - blocksToKeep = 0, - epochLength = epochLength, - useLastEpochs = useLastEpochs, - initialDiffOpt = Some(initDiff) - ) - val blocksBeforeRecalculate = epochLength + 1 - - history = applyHeaderChain(history, - genHeaderChain(blocksBeforeRecalculate, history, diffBitsOpt = Some(initDiffBits), useRealTs = true)) - - val bestHeaderOpt = history.bestHeaderOpt - - history.requiredDifficultyAfter(bestHeaderOpt.get) shouldBe initDiff - } - - property("lastHeaders() should return correct number of blocks") { - forAll(smallInt) { m => - val lastHeaders = popowHistory.lastHeaders(m) - if (m > 0) { - lastHeaders.last shouldBe popowHistory.bestHeaderOpt.get - } - lastHeaders.length shouldBe m - } - } - - property("lastHeaders() should be sorted") { - forAll(smallInt) { m => - val lastHeaderTimestamps = popowHistory.lastHeaders(m).headers.map(_.timestamp) - lastHeaderTimestamps shouldBe lastHeaderTimestamps.sorted - } - } - - property("History.isInBestChain") { - var history = genHistory() - val common = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, common) - - val fork1 = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - val fork2 = genHeaderChain(BlocksInChain + 1, history, diffBitsOpt = None, useRealTs = false) - - history = applyHeaderChain(history, fork1.tail) - history.bestHeaderOpt.get shouldBe fork1.last - fork1.headers.foreach(h => history.isInBestChain(h.id) shouldBe true) - - history = applyHeaderChain(history, fork2.tail) - history.bestHeaderOpt.get shouldBe fork2.last - fork2.headers.foreach(h => history.isInBestChain(h.id) shouldBe true) - fork1.tail.headers.foreach(h => history.isInBestChain(h.id) shouldBe false) - } - - property("Compare headers chain") { - var history = genHistory() - - def getInfoV1(c: HeaderChain): ErgoSyncInfo = ErgoSyncInfoV1(c.headers.map(_.id)) - def getInfoV2(c: HeaderChain): ErgoSyncInfo = ErgoSyncInfoV2(Seq(c.headers.last)) - - // generate common chain prefix - val common = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, common) - - val fork1 = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - val fork2 = genHeaderChain(BlocksInChain + 1, history, diffBitsOpt = None, useRealTs = false) - - history = applyHeaderChain(history, fork1.tail) - history.bestHeaderOpt.get shouldBe fork1.last - - // v1 sync - history.compare(getInfoV1(fork2)) shouldBe Fork - history.compare(getInfoV1(fork1)) shouldBe Equal - history.compare(getInfoV1(fork1.take(BlocksInChain - 1))) shouldBe Fork - history.compare(getInfoV1(fork2.take(BlocksInChain - 1))) shouldBe Fork - history.compare(getInfoV1(fork2.tail)) shouldBe Older - - // v2 sync - history.compare(getInfoV2(fork2)) shouldBe Older - history.compare(getInfoV2(fork1)) shouldBe Equal - history.compare(getInfoV2(fork1.take(BlocksInChain - 1))) shouldBe Younger - history.compare(getInfoV2(fork2.take(BlocksInChain - 1))) shouldBe Younger - history.compare(getInfoV2(fork2.tail)) shouldBe Older - } - - property("continuationIds() on forks") { - var history1 = genHistory() - var history2 = genHistory() - val inChain = genHeaderChain(20, history1, diffBitsOpt = None, useRealTs = false) - - //put genesis - history1 = applyHeaderChain(history1, inChain) - history2 = applyHeaderChain(history2, inChain) - val fork1 = genHeaderChain(BlocksInChain, history1, diffBitsOpt = None, useRealTs = false).tail - val fork2 = genHeaderChain(BlocksInChain, history1, diffBitsOpt = None, useRealTs = false).tail - - //apply 2 different forks - history1 = applyHeaderChain(history1, fork1) - history2 = applyHeaderChain(history2, fork1.take(BlocksInChain / 3)) - history2 = applyHeaderChain(history2, fork2.take(BlocksInChain / 2)) - history2.bestHeaderOpt.get shouldBe fork2.take(BlocksInChain / 2).last - history1.bestHeaderOpt.get shouldBe fork1.last - - val si = history2.syncInfoV1 - val continuation = history1.continuationIds(si, BlocksInChain * 100) - fork1.headers.foreach(h => continuation.exists(_._2 == h.id) shouldBe true) - - val si2 = history2.syncInfoV2(full = true) - val continuation2 = history1.continuationIds(si2, BlocksInChain * 100) - fork1.headers.foreach(h => continuation2.exists(_._2 == h.id) shouldBe true) - } - - property("continuationIds() for empty ErgoSyncInfo should contain ids of all headers") { - var history = genHistory() - val chain = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, chain) - - val smallerLimit = 2 - val ci0v1 = history.continuationIds(ErgoSyncInfoV1(Seq()), smallerLimit) - ci0v1.length shouldBe smallerLimit - - val ci0v2 = history.continuationIds(ErgoSyncInfoV2(Seq()), smallerLimit) - ci0v2.length shouldBe smallerLimit - - chain.headers.take(smallerLimit).map(_.encodedId) shouldEqual ci0v1.map(c => Algos.encode(c._2)) - chain.headers.take(smallerLimit).map(_.encodedId) shouldEqual ci0v2.map(c => Algos.encode(c._2)) - - val biggerLimit = BlocksInChain + 2 - val ci1v1 = history.continuationIds(ErgoSyncInfoV1(Seq()), biggerLimit) - chain.headers.map(_.id) should contain theSameElementsAs ci1v1.map(_._2) - val ci1v2 = history.continuationIds(ErgoSyncInfoV2(Seq()), biggerLimit) - chain.headers.map(_.id) should contain theSameElementsAs ci1v2.map(_._2) - - val civ1 = history.continuationIds(ErgoSyncInfoV1(Seq()), BlocksInChain) - civ1.foreach(c => c._1 shouldBe Header.modifierTypeId) - chain.headers.map(_.id) should contain theSameElementsAs civ1.map(_._2) - val civ2 = history.continuationIds(ErgoSyncInfoV2(Seq()), BlocksInChain) - civ2.foreach(c => c._1 shouldBe Header.modifierTypeId) - chain.headers.map(_.id) should contain theSameElementsAs civ2.map(_._2) - } - - property("continuationIds() for smaller chain should contain ids of next headers in our chain") { - var history = genHistory() - - history = ensureMinimalHeight(history, BlocksInChain + 1) - val chain = history.lastHeaders(BlocksInChain) - - forAll(smallPositiveInt) { forkLength: Int => - whenever(forkLength > 1 && chain.size > forkLength) { - val siv1 = ErgoSyncInfoV1(Seq(chain.headers(chain.size - forkLength - 1).id)) - val continuation1 = history.continuationIds(siv1, forkLength + 1) - continuation1.length shouldBe forkLength + 1 - continuation1.last._2 shouldEqual chain.last.id - continuation1.head._2 shouldEqual chain.headers(chain.size - forkLength - 1).id - - val siv2 = ErgoSyncInfoV2(Seq(chain.headers(chain.size - forkLength - 1))) - val continuation2 = history.continuationIds(siv2, forkLength + 1) - continuation2.length shouldBe forkLength - continuation2.last._2 shouldEqual chain.last.id - continuation2.head._2 shouldEqual chain.headers(chain.size - forkLength).id - } - } - } - - property("continuationHeaderChains()") { - var history = genHistory() - //put 2 blocks - val inChain = genHeaderChain(2, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, inChain) - //apply 2 different forks - val fork1 = genHeaderChain(2, history, diffBitsOpt = None, useRealTs = false).tail - val fork2 = genHeaderChain(3, history, diffBitsOpt = None, useRealTs = false).tail - history = applyHeaderChain(history, fork1) - history = applyHeaderChain(history, fork2) - //get continuationHeaderChains - val continuations = history.continuationHeaderChains(inChain.last, _ => true) - continuations.length shouldBe 2 - continuations.flatMap(_.tail).map(_.encodedId).toSet should contain theSameElementsAs - (fork1.headers ++ fork2.headers).map(_.encodedId).toSet - } - - property("chainToHeader()") { - var history = genHistory() - //put 2 blocks - val inChain = genHeaderChain(2, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, inChain) - //apply 2 different forks - val fork1 = genHeaderChain(2, history, diffBitsOpt = None, useRealTs = false).tail - val fork2 = genHeaderChain(3, history, diffBitsOpt = None, useRealTs = false).tail - history = applyHeaderChain(history, fork1) - history = applyHeaderChain(history, fork2) - - val fork1Chain = history.chainToHeader(None, fork1.last) - fork1Chain._1 shouldBe None - fork1Chain._2 shouldEqual HeaderChain(inChain.headers ++ fork1.headers) - - val from1to2Chain = history.chainToHeader(Some(fork1.last), fork2.last) - from1to2Chain._1.get shouldEqual inChain.last.id - from1to2Chain._2.headers.map(_.height) shouldEqual fork2.headers.map(_.height) - from1to2Chain._2.headers shouldEqual fork2.headers - } - - property("commonBlockThenSuffixes()") { - var history = genHistory() - - history = ensureMinimalHeight(history, BlocksInChain + 1) - - val forkDepth = BlocksInChain / 2 - forAll(smallInt, digest32Gen) { (forkLength: Int, extensionHash: Digest32) => - whenever(forkLength > forkDepth) { - - val fork1 = genHeaderChain(forkLength, history, diffBitsOpt = None, useRealTs = false).tail - val common = fork1.headers(forkDepth) - history.typedModifierById[Extension](common.extensionId) - .map(ext => NipopowAlgos.unpackInterlinks(ext.fields).get) - .getOrElse(Seq.empty) - val fork2 = fork1.take(forkDepth) ++ genHeaderChain(forkLength + 1, Option(common), - defaultDifficultyControl, extensionHash, diffBitsOpt = None, useRealTs = false) - val fork1SuffixIds = fork1.headers.drop(forkDepth + 1).map(_.encodedId) - val fork2SuffixIds = fork2.headers.drop(forkDepth + 1).map(_.encodedId) - (fork1SuffixIds intersect fork2SuffixIds) shouldBe empty - - history = applyHeaderChain(history, fork1) - history.bestHeaderOpt.get shouldBe fork1.last - - val (our, their) = history.commonBlockThenSuffixes(fork2, history.bestHeaderOpt.get, 1000) - our.head shouldBe their.head - our.head shouldBe common - our.last shouldBe fork1.last - their.last shouldBe fork2.last - } - } - } - - property("Append headers to best chain in history") { - var history = genHistory() - - val chain = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) - - chain.headers.foreach { header => - val inHeight = history.heightOf(header.parentId).getOrElse(ErgoHistory.EmptyHistoryHeight) - - history.contains(header) shouldBe false - history.applicable(header) shouldBe true - - history = history.append(header).get._1 - - history.contains(header) shouldBe true - history.applicable(header) shouldBe false - history.bestHeaderOpt.get shouldBe header - history.heightOf(header.id).get shouldBe (inHeight + 1) - } - } - - property("bestHeadersAfter returns correct number of headers") { - val chainLength = 50 - - var history = genHistory() - val chain = genHeaderChain(chainLength, history, diffBitsOpt = None, useRealTs = false) - - history = applyHeaderChain(history, chain) - - val suffixLength = Random.nextInt(chainLength - 1) + 1 - val hdr = chain.headers.takeRight(suffixLength).head - val count = Random.nextInt(suffixLength) - history.bestHeadersAfter(hdr, count).length shouldBe count - - history.bestHeadersAfter(chain.last, 0).length shouldBe 0 - history.bestHeadersAfter(chain.last, 1).length shouldBe 0 - history.bestHeadersAfter(chain.last, Int.MaxValue).length shouldBe 0 - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/PopowProcessorSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/PopowProcessorSpecification.scala deleted file mode 100644 index b0d148c6b2..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/PopowProcessorSpecification.scala +++ /dev/null @@ -1,33 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.popow.PoPowHeader -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.util.ModifierId - -class PopowProcessorSpecification extends HistoryTestHelpers { - - private def genHistory(genesisIdOpt: Option[ModifierId], popowBootstrap: Boolean) = - generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = popowBootstrap, blocksToKeep = -1, - epochLength = 10000, useLastEpochs = 3, initialDiffOpt = None, genesisIdOpt) - .ensuring(_.bestFullBlockOpt.isEmpty) - - val toPoPoWChain = (c: Seq[ErgoFullBlock]) => c.map(b => PoPowHeader.fromBlock(b).get) - - property("popow proof application") { - val senderHistory = genHistory(None, popowBootstrap = false) - val senderChain = genChain(5000, senderHistory) - applyChain(senderHistory, senderChain) - - val popowProofBytes = senderHistory.popowProofBytes().get - val popowProof = senderHistory.nipopowSerializer.parseBytes(popowProofBytes) - - val receiverHistory = genHistory(senderHistory.bestHeaderAtHeight(1).map(_.id), popowBootstrap = true) - receiverHistory.headersHeight shouldBe 0 - receiverHistory.applyPopowProof(popowProof) - receiverHistory.headersHeight shouldBe senderHistory.headersHeight - receiverHistory.bestHeaderOpt.get shouldBe senderHistory.bestHeaderOpt.get - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala deleted file mode 100644 index 3903251054..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala +++ /dev/null @@ -1,94 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.nodeView.history.storage.HistoryStorage -import org.ergoplatform.nodeView.history.storage.modifierprocessors.UtxoSetSnapshotProcessor -import org.ergoplatform.nodeView.state.{StateType, UtxoState} -import org.ergoplatform.settings.{Algos, ErgoSettings} -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.core.VersionTag -import scorex.core.serialization.{ManifestSerializer, SubtreeSerializer} -import scorex.db.LDBVersionedStore -import scorex.util.ModifierId - -import scala.util.Random - -class UtxoSetSnapshotProcessorSpecification extends HistoryTestHelpers { - - private val s = settings - - val epochLength = 20 - - val utxoSetSnapshotProcessor = new UtxoSetSnapshotProcessor { - var minimalFullBlockHeightVar = ErgoHistory.GenesisHeight - override protected val settings: ErgoSettings = s.copy(chainSettings = - s.chainSettings.copy(voting = s.chainSettings.voting.copy(votingLength = epochLength))) - override protected val historyStorage: HistoryStorage = HistoryStorage(settings) - override def readMinimalFullBlockHeight() = minimalFullBlockHeightVar - override def writeMinimalFullBlockHeight(height: Int): Unit = { - minimalFullBlockHeightVar = height - } - } - - var history = generateHistory( - verifyTransactions = true, - StateType.Utxo, - PoPoWBootstrap = false, - blocksToKeep = -1, - epochLength = epochLength, - useLastEpochs = 2, - initialDiffOpt = None) - - val chain = genHeaderChain(epochLength + 1, history, diffBitsOpt = None, useRealTs = false) - history = applyHeaderChain(history, chain) - - property("registerManifestToDownload + getUtxoSetSnapshotDownloadPlan + getChunkIdsToDownload") { - val bh = boxesHolderGenOfSize(32 * 1024).sample.get - val us = createUtxoState(bh, parameters) - - val snapshotHeight = epochLength - 1 - val serializer = ManifestSerializer.defaultSerializer - - us.dumpSnapshot(snapshotHeight, us.rootDigest.dropRight(1)) - val manifestId = us.snapshotsDb.readSnapshotsInfo.availableManifests.apply(snapshotHeight) - val manifestBytes = us.snapshotsDb.readManifestBytes(manifestId).get - val manifest = serializer.parseBytes(manifestBytes) - val subtreeIds = manifest.subtreesIds - val subtreeIdsEncoded = subtreeIds.map(id => ModifierId @@ Algos.encode(id)) - - subtreeIds.foreach {sid => - val subtreeBytes = us.snapshotsDb.readSubtreeBytes(sid).get - val subtree = SubtreeSerializer.parseBytes(subtreeBytes) - subtree.verify(sid) shouldBe true - } - - val blockId = ModifierId @@ Algos.encode(Array.fill(32)(Random.nextInt(100).toByte)) - utxoSetSnapshotProcessor.registerManifestToDownload(manifest, snapshotHeight, Seq.empty) - val dp = utxoSetSnapshotProcessor.utxoSetSnapshotDownloadPlan().get - dp.snapshotHeight shouldBe snapshotHeight - val expected = dp.expectedChunkIds.map(id => ModifierId @@ Algos.encode(id)) - expected shouldBe subtreeIdsEncoded - val toDownload = utxoSetSnapshotProcessor.getChunkIdsToDownload(expected.size).map(id => ModifierId @@ Algos.encode(id)) - toDownload shouldBe expected - - subtreeIds.foreach { subtreeId => - val subtreeBytes = us.snapshotsDb.readSubtreeBytes(subtreeId).get - utxoSetSnapshotProcessor.registerDownloadedChunk(subtreeId, subtreeBytes) - } - val s = utxoSetSnapshotProcessor.downloadedChunksIterator().map(s => ModifierId @@ Algos.encode(s.id)).toSeq - s shouldBe subtreeIdsEncoded - - val dir = createTempDir - val store = new LDBVersionedStore(dir, initialKeepVersions = 100) - val restoredProver = utxoSetSnapshotProcessor.createPersistentProver(store, history, snapshotHeight, blockId).get - bh.sortedBoxes.foreach { box => - restoredProver.unauthenticatedLookup(box.id).isDefined shouldBe true - } - restoredProver.checkTree(postProof = false) - val restoredState = new UtxoState(restoredProver, version = VersionTag @@@ blockId, store, settings) - restoredState.stateContext.currentHeight shouldBe (epochLength - 1) - bh.sortedBoxes.foreach { box => - restoredState.boxById(box.id).isDefined shouldBe true - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala deleted file mode 100644 index 0240d00afb..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala +++ /dev/null @@ -1,497 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.HeaderChain -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection} -import org.ergoplatform.nodeView.ErgoModifiersCache -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.core.consensus.ProgressInfo -import scorex.core.consensus.ModifierSemanticValidity.{Absent, Invalid, Unknown, Valid} -import scorex.testkit.utils.NoShrink - -import scala.collection.mutable.ArrayBuffer -import scala.util.Random - -class VerifyADHistorySpecification extends HistoryTestHelpers with NoShrink { - - type PM = BlockSection - - private def genHistory(blocksNum: Int = 0, - minFullHeight: Option[Int] = Some(ErgoHistory.GenesisHeight)): (ErgoHistory, Seq[ErgoFullBlock]) = { - val inHistory = generateHistory(verifyTransactions = true, StateType.Digest, PoPoWBootstrap = false, BlocksToKeep) - minFullHeight.foreach { h => - inHistory.writeMinimalFullBlockHeight(h) - inHistory.isHeadersChainSyncedVar = true - } - - if (blocksNum > 0) { - val chain = genChain(blocksNum, inHistory) - (applyChain(inHistory, chain), chain) - } else { - (inHistory, Seq.empty) - } - } - - property("Forks that include genesis block") { - var (history, _) = genHistory() - val fork1 = genChain(3, history) - val fork2 = genChain(2, history) - val fork3 = genChain(4, history) - - // apply 3 headers long chain - history = applyChain(history, fork1) - history.bestFullBlockOpt.get.header shouldBe history.bestHeaderOpt.get - history.bestHeaderOpt.get shouldBe fork1.last.header - - // apply 2 headers long chain, should stay on previous one - history = applyChain(history, fork2) - history.bestFullBlockOpt.get.header shouldBe history.bestHeaderOpt.get - history.bestHeaderOpt.get shouldBe fork1.last.header - - // apply 4 headers long chain, should update chain - history = applyChain(history, fork3) - history.bestHeaderOpt.get shouldBe fork3.last.header - history.bestFullBlockOpt.get.header.height shouldBe fork3.last.header.height - - } - - - property("ErgoModifiersCache.findCandidateKey() should find headers in case of forks") { - val modifiersCache = new ErgoModifiersCache(Int.MaxValue) - - var (history, _) = genHistory(2) - - val fork1 = genChain(2, history).tail - val fork2 = genChain(3, history).tail - - history = applyChain(history, fork1) - - fork2.foreach { fb => - modifiersCache.put(fb.header.id, fb.header) - } - history.applicable(fork2.head.header) shouldBe true - modifiersCache.contains(fork2.head.header.id) shouldBe true - modifiersCache.findCandidateKey(history).isDefined shouldBe true - } - - property("should not be able to apply blocks older than blocksToKeep") { - var history = genHistory()._1 - history.bestFullBlockOpt shouldBe None - - val chain = genChain(BlocksToKeep * 2) - - history = applyHeaderChain(history, HeaderChain(chain.map(_.header))) - history.bestHeaderOpt.get shouldBe chain.last.header - history.bestFullBlockOpt shouldBe None - - val fullBlocksToApply = chain.tail - history.updateBestFullBlock(fullBlocksToApply(BlocksToKeep - 1).header) - - history.applicable(chain.head.blockTransactions) shouldBe false - - history = applyBlock(history, fullBlocksToApply.head) - history.bestFullBlockOpt.get.header shouldBe fullBlocksToApply.head.header - - history.applicable(chain.head.blockTransactions) shouldBe false - - fullBlocksToApply.tail.foreach { f => - history = applyBlock(history, f) - } - history.bestFullBlockOpt.get.header shouldBe fullBlocksToApply.last.header - - //block sections should be already pruned - fullBlocksToApply.head.header.sectionIds.foreach(id => history.contains(id._2) shouldBe false) - - //block transactions should not be able to apply since they are too far back in history - fullBlocksToApply.head.blockSections.foreach(s => history.applicable(s) shouldBe false) - } - - property("proofs and transactions application in random order with forks") { - forAll(smallInt, positiveLongGen) { (chainHeight, seed) => - whenever(chainHeight > 0) { - val (history, chain) = genHistory(1) - val r = new Random(seed) - val genesis = chain.head - history.bestFullBlockOpt shouldBe Some(genesis) - - val chains = Seq(genChain(chainHeight, genesis), genChain(chainHeight + 1, genesis)).map(_.tail) - chains.foreach(chain => applyHeaderChain(history, HeaderChain(chain.map(_.header)))) - val indices: Seq[(Int, Int)] = chains.indices.flatMap { chainIndex => - val chain = chains(chainIndex) - chain.indices.map(blockIndex => (chainIndex, blockIndex)) - } - - val appended: ArrayBuffer[ErgoFullBlock] = ArrayBuffer.empty - - def findBestBlock(appendedToCheck: Seq[ErgoFullBlock]): ErgoFullBlock = { - def firstInAppended(h: Header): Header = { - appended.find(_.header.id == h.parentId).map(_.header) match { - case Some(prev) => firstInAppended(prev) - case None => h - } - } - - if (appendedToCheck.isEmpty) { - genesis - } else { - val best = appendedToCheck.maxBy(_.header.height) - if (firstInAppended(best.header).parentId == genesis.id) { - best - } else { - findBestBlock(appendedToCheck.filterNot(_.id == best.id)) - } - } - } - - r.shuffle(indices).foreach { i => - val block = chains(i._1)(i._2) - val sectionsToAppend = block.blockSections.filterNot(_.modifierTypeId == Extension.modifierTypeId) - r.shuffle(sectionsToAppend).foreach(s => history.append(s) shouldBe 'success) - - appended += block - - sectionsToAppend.forall(history.contains) shouldBe true - } - } - } - } - - property("apply proofs that link incomplete chain") { - var history = genHistory()._1 - val chain = genChain(4) - - val block0 = chain.head - val block1 = chain(1) - val block2 = chain(2) - val block3 = chain(3) - - applyHeaderChain(history, HeaderChain(chain.map(_.header))) - history.bestFullBlockOpt shouldBe None - history.bestHeaderOpt shouldBe Some(block3.header) - - history = applySection(history, block0.adProofs.get) - history.contains(block0.adProofs.get.id) shouldBe true - - history = applySection(history, block2.adProofs.get) - history.contains(block2.adProofs.get.id) shouldBe true - - history = applySection(history, block3.adProofs.get) - history.contains(block3.adProofs.get.id) shouldBe true - - history = applySection(history, block1.adProofs.get) - history.contains(block1.adProofs.get.id) shouldBe true - - history = applyBlock(history, block0) - history = applyBlock(history, block1) - history = applyBlock(history, block2) - history = applyBlock(history, block3) - - history.bestFullBlockOpt shouldBe Some(block3) - } - - property("bootstrap from headers and last full blocks") { - var history = genHistory()._1 - history.bestFullBlockOpt shouldBe None - - val chain = genChain(BlocksToKeep * 2) - - history = applyHeaderChain(history, HeaderChain(chain.map(_.header))) - history.bestHeaderOpt.value shouldBe chain.last.header - history.bestFullBlockOpt shouldBe None - history.updateBestFullBlock(chain.last.header) - - val fullBlocksToApply = chain.takeRight(BlocksToKeep) - - history = applyBlock(history, fullBlocksToApply.head) - history.bestFullBlockOpt.value.header shouldBe fullBlocksToApply.head.header - } - - property("syncInfo()") { - val (history, chain) = genHistory(BlocksInChain) - - val si = history.syncInfoV1.asInstanceOf[ErgoSyncInfoV1] - si.lastHeaderIds.last shouldEqual chain.last.header.id - } - - property("reportModifierIsValid should set isSemanticallyValid() result") { - var history = genHistory(1)._1 - history.bestFullBlockOpt.isDefined shouldBe true - - val chain = genChain(BlocksInChain, history).tail - chain.head.parentId shouldEqual history.bestFullBlockOpt.value.id - - chain.foreach { fullBlock => - history.bestHeaderOpt.foreach(b => b.id shouldEqual fullBlock.parentId) - history.bestFullBlockOpt.foreach(b => b.header shouldBe history.bestHeaderOpt.value) - - history.isSemanticallyValid(fullBlock.header.id) shouldBe Absent - fullBlock.blockSections.foreach(s => history.isSemanticallyValid(s.id) shouldBe Absent) - - history = applyBlock(history, fullBlock) - - history.bestFullBlockOpt.value.header shouldBe history.bestHeaderOpt.value - history.bestHeaderOpt.value.id shouldEqual fullBlock.header.id - - history.isSemanticallyValid(fullBlock.header.id) shouldBe Unknown - fullBlock.blockSections.foreach(s => history.isSemanticallyValid(s.id) shouldBe Unknown) - - history.reportModifierIsValid(fullBlock.header) - fullBlock.blockSections.foreach(s => history.reportModifierIsValid(s)) - - history.reportModifierIsValid(fullBlock) - - history.isSemanticallyValid(fullBlock.header.id) shouldBe Valid - fullBlock.blockSections.foreach(s => history.isSemanticallyValid(s.id) shouldBe Valid) - } - } - - property("reportModifierIsInvalid should set isSemanticallyValid() result for all linked modifiers") { - var history = genHistory(1)._1 - - history.bestFullBlockOpt should not be None - - val chain = genChain(BlocksInChain, history.bestFullBlockOpt.get).tail - (chain.head.header.parentId == Header.GenesisParentId) shouldBe false - - history = applyChain(history, chain) - - chain.reverse.foreach { fullBlock => - history.isSemanticallyValid(fullBlock.header.id) shouldBe Unknown - history.isSemanticallyValid(fullBlock.adProofs.value.id) shouldBe Unknown - history.isSemanticallyValid(fullBlock.blockTransactions.id) shouldBe Unknown - - - val progressInfo = ProgressInfo[PM](Option(fullBlock.header.parentId), Seq(fullBlock), Seq.empty, Seq.empty) - history.reportModifierIsInvalid(fullBlock.header, progressInfo) - - history.isSemanticallyValid(fullBlock.header.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.adProofs.value.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.blockTransactions.id) shouldBe Invalid - } - } - - property("reportModifierIsInvalid should mark invalid all forks containing this header") { - var (history, inChain) = genHistory(2) - - val fork1 = genChain(3, history).tail - val fork2 = genChain(3, history).tail - fork1.head.parentId shouldEqual fork2.head.parentId - - history = applyChain(history, fork1) - history = applyChain(history, fork2) - - val progressInfo = ProgressInfo[PM](Some(inChain.last.parentId), fork2, Seq.empty, Seq.empty) - history.reportModifierIsInvalid(inChain.last.header, progressInfo) - - fork1.foreach { fullBlock => - history.isSemanticallyValid(fullBlock.header.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.adProofs.value.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.blockTransactions.id) shouldBe Invalid - } - - fork2.foreach { fullBlock => - history.isSemanticallyValid(fullBlock.header.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.adProofs.value.id) shouldBe Invalid - history.isSemanticallyValid(fullBlock.blockTransactions.id) shouldBe Invalid - } - } - - property("reportModifierIsInvalid should return blocks to rollback and to process") { - var history = genHistory(3)._1 - val common = history.bestFullBlockOpt.value - - val fork1 = genChain(3, common).tail - val fork2 = genChain(2, common).tail - - history = applyChain(history, fork1) - history = applyChain(history, fork2) - - history.bestHeaderOpt.value shouldBe fork1.last.header - - val progressInfo = ProgressInfo[PM](Some(common.parentId), fork1, Seq.empty, Seq.empty) - history.reportModifierIsInvalid(fork1.head.header, progressInfo) - - history.bestHeaderOpt.value shouldBe fork2.last.header - history.bestFullBlockOpt.value shouldBe fork2.last - } - - property("reportModifierIsInvalid for non-last block in best chain without better forks") { - var (history, chain) = genHistory(BlocksInChain) - - history.bestFullBlockOpt.value.header shouldBe history.bestHeaderOpt.value - history.bestHeaderOpt.value shouldEqual chain.last.header - - val invalidChain = chain.takeRight(2) - - val progressInfo = ProgressInfo[PM](Some(invalidChain.head.parentId), invalidChain, Seq.empty, Seq.empty) - val report = history.reportModifierIsInvalid(invalidChain.head.header, progressInfo).get - history = report._1 - val processInfo = report._2 - processInfo.toApply.isEmpty shouldBe true - processInfo.branchPoint.value shouldEqual invalidChain.head.header.parentId - processInfo.toRemove shouldEqual invalidChain - - history.bestFullBlockOpt.value.header shouldBe history.bestHeaderOpt.value - history.bestHeaderOpt.value.id shouldEqual invalidChain.head.parentId - } - - property("Report invalid for best full block") { - val (history, chain) = genHistory(BlocksInChain) - - chain.takeRight(BlocksToKeep - 2).reverse.foreach { fullBlock => - history.bestFullBlockOpt.value.header shouldBe history.bestHeaderOpt.value - history.bestHeaderOpt.value shouldEqual fullBlock.header - - val parentHeader = history.typedModifierById[Header](fullBlock.header.parentId).value - history.contains(parentHeader.transactionsId) shouldBe true - history.contains(parentHeader.ADProofsId) shouldBe true - - val progressInfo = ProgressInfo[PM](Some(parentHeader.id), Seq(fullBlock), Seq.empty, Seq.empty) - val (repHistory, _) = history.reportModifierIsInvalid(fullBlock.blockTransactions, progressInfo).get - repHistory.bestFullBlockOpt.value.header shouldBe history.bestHeaderOpt.value - repHistory.bestHeaderOpt.value shouldBe parentHeader - } - } - - property("prune old blocks test") { - val blocksToPrune = 20 - - val (history, chain) = genHistory(BlocksToKeep + blocksToPrune + 1) - - history.bestHeaderOpt.value shouldBe chain.last.header - history.bestFullBlockOpt.value.header shouldBe chain.last.header - - //genesis block is not pruned - chain.take(blocksToPrune).tail.foreach { b => - history.modifierById(b.header.transactionsId) shouldBe None - history.modifierById(b.header.ADProofsId) shouldBe None - } - - chain.takeRight(BlocksToKeep).foreach { b => - history.modifierById(b.header.transactionsId).isDefined shouldBe true - history.modifierById(b.header.ADProofsId).isDefined shouldBe true - } - } - - property("process fork from genesis") { - var (history, c) = genHistory(1) - val genesis = c.head - val fork1 = genChain(1, history.bestFullBlockOpt.value).tail - val fork2 = genChain(2, history.bestFullBlockOpt.value).tail - - history = applyChain(history, fork1) - history.bestHeaderOpt.value shouldBe fork1.last.header - - history = applyChain(history, fork2.dropRight(1)) - val lastBlock = fork2.last - history = history.append(lastBlock.header).get._1 - .append(lastBlock.blockTransactions).get._1 - .append(lastBlock.extension).get._1 - - val changes = history.append(lastBlock.adProofs.value).get - history = changes._1 - history.bestHeaderOpt.value shouldBe fork2.last.header - - val processInfo = changes._2 - processInfo.branchPoint.get shouldEqual genesis.id - processInfo.toRemove should contain theSameElementsAs fork1 - processInfo.toApply should contain theSameElementsAs fork2 - - } - - property("process fork from existing chain") { - var history = genHistory(BlocksInChain)._1 - - history.bestFullBlockOpt.isDefined should not be None - forAll(smallPositiveInt) { forkLength: Int => - whenever(forkLength > 0) { - val branchPoint = history.bestFullBlockOpt.value - val fork1 = genChain(forkLength, branchPoint).tail - val fork2 = genChain(forkLength + 1, branchPoint).tail - - history = applyChain(history, fork1) - history.bestHeaderOpt.value shouldBe fork1.last.header - - history = applyChain(history, fork2.dropRight(1)) - val lastBlock = fork2.last - history = history.append(lastBlock.header).get._1 - .append(lastBlock.extension).get._1 - .append(lastBlock.blockTransactions).get._1 - - val changes = history.append(lastBlock.adProofs.value).get - history = changes._1 - history.bestHeaderOpt.value shouldBe fork2.last.header - - val processInfo = changes._2 - processInfo.branchPoint.value shouldEqual branchPoint.id - processInfo.toRemove should contain theSameElementsAs fork1 - processInfo.toApply should contain theSameElementsAs fork2 - } - } - } - - property("Appended full blocks to best chain in full history") { - var history = genHistory(1)._1 - history.bestFullBlockOpt.nonEmpty shouldBe true - - val chain = genChain(BlocksInChain, history).tail - chain.foreach { fullBlock => - val startFullBlock = history.bestFullBlockOpt.value - val header = fullBlock.header - val txs = fullBlock.blockTransactions - val proofs = fullBlock.adProofs.value - val extension = fullBlock.extension - history.contains(header) shouldBe false - history.contains(txs) shouldBe false - history.contains(proofs) shouldBe false - history.contains(extension) shouldBe false - history.applicable(header) shouldBe true - history.applicable(proofs) shouldBe false - history.applicable(txs) shouldBe false - history.applicable(extension) shouldBe false - - history = history.append(header).get._1 - - history.contains(header) shouldBe true - history.contains(txs) shouldBe false - history.contains(proofs) shouldBe false - history.contains(extension) shouldBe false - history.applicable(header) shouldBe false - history.applicable(proofs) shouldBe true - history.applicable(txs) shouldBe true - history.applicable(extension) shouldBe true - history.bestHeaderOpt.get shouldBe header - history.bestFullBlockOpt.get shouldBe startFullBlock - - history = history.append(txs).get._1 - - history.contains(header) shouldBe true - history.contains(txs) shouldBe true - history.contains(proofs) shouldBe false - history.contains(extension) shouldBe false - history.applicable(header) shouldBe false - history.applicable(proofs) shouldBe true - history.applicable(extension) shouldBe true - history.applicable(txs) shouldBe false - history.bestHeaderOpt.get shouldBe header - history.bestFullBlockOpt.get shouldBe startFullBlock - - history = history.append(proofs).get._1 - history = history.append(extension).get._1 - - history.contains(header) shouldBe true - history.contains(txs) shouldBe true - history.contains(proofs) shouldBe true - history.contains(extension) shouldBe true - history.applicable(header) shouldBe false - history.applicable(proofs) shouldBe false - history.applicable(extension) shouldBe false - history.applicable(txs) shouldBe false - history.bestHeaderOpt.value shouldBe header - history.bestFullBlockOpt.value shouldBe fullBlock - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala deleted file mode 100644 index cb024dd9bb..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/VerifyNonADHistorySpecification.scala +++ /dev/null @@ -1,217 +0,0 @@ -package org.ergoplatform.nodeView.history - -import org.ergoplatform.modifiers.{ErgoFullBlock, NetworkObjectTypeId} -import org.ergoplatform.modifiers.history._ -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.HeaderSerializer -import org.ergoplatform.nodeView.history.storage.modifierprocessors.FullBlockProcessor -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.HistoryTestHelpers -import scorex.core.consensus.ProgressInfo - -class VerifyNonADHistorySpecification extends HistoryTestHelpers { - import scorex.core.utils.MapPimp - - private def genHistory() = - generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, BlocksToKeep) - - property("block sections application in incorrect order") { - var history = genHistory() - val chain = genChain(6, history) - if (!history.isHeadersChainSynced) { - history.updateBestFullBlock(chain.last.header) - } - history = applyHeaderChain(history, HeaderChain(chain.map(_.header))) - chain.foreach(fb => history.append(fb.extension).get) - - history = history.append(chain(1).blockTransactions).get._1 - history.bestFullBlockOpt shouldBe None - val pi1 = history.append(chain(0).blockTransactions).get._2 - history.bestFullBlockOpt.value shouldBe chain(1) - pi1.toApply.length shouldBe 2 - - chain.drop(3).foreach(c => history.append(c.blockTransactions)) - history.bestFullBlockOpt.value.header.height shouldBe chain(1).header.height - - val (hi, pi) = history.append(chain(2).blockTransactions).get - val expected = chain.drop(2) - - expected.forall(b => hi.asInstanceOf[FullBlockProcessor].isInBestFullChain(b.id)) shouldBe true - - pi.toApply.map(_.asInstanceOf[ErgoFullBlock]) shouldBe expected - } - - property("full chain status updating") { - - def isInBestChain(b: ErgoFullBlock, h: ErgoHistory): Boolean = { - h.asInstanceOf[FullBlockProcessor].isInBestFullChain(b.id) - } - - var history = genHistory() - val initChain = genChain(6, history) - - val stableChain = initChain.take(3) - val altChain = genChain(8, stableChain.last).tail - - // apply initial initChain (1 to 6) - history = applyChain(history, initChain) - - history.bestFullBlockIdOpt.get shouldEqual initChain.last.id - initChain.forall(b => isInBestChain(b, history)) shouldBe true - - // apply better initChain forking initial one (1 to 3 (init initChain), 3 to 11 (new initChain)) - history = applyChain(history, altChain) - - history.bestFullBlockIdOpt.get shouldEqual altChain.last.id - // first blocks from init chain are still marked as best chain - stableChain.forall(b => isInBestChain(b, history)) shouldBe true - // other blocks from init chain are no more in best chain - initChain.drop(3).forall(b => !isInBestChain(b, history)) shouldBe true - // all blocks from fork are marked as best chain - altChain.forall(b => isInBestChain(b, history)) shouldBe true - - val invalidChainHead = altChain.head - - // invalidate modifier from fork - history.reportModifierIsInvalid(invalidChainHead.blockTransactions, - ProgressInfo(None, Seq.empty, Seq.empty, Seq.empty)) - - history.bestFullBlockIdOpt.get shouldEqual initChain.last.id - - // all blocks from init chain are marked as best chain again - initChain.forall(b => isInBestChain(b, history)) shouldBe true - // blocks from fork no longer marked as best chain - altChain.forall(b => !isInBestChain(b, history)) shouldBe true - } - - property("bootstrap from headers and last full blocks") { - var history = genHistory() - history.bestFullBlockOpt shouldBe None - - val chain = genChain(BlocksToKeep * 2) - - history = applyHeaderChain(history, HeaderChain(chain.map(_.header))) - history.bestHeaderOpt.value shouldBe chain.last.header - history.bestFullBlockOpt shouldBe None - - if (!history.isHeadersChainSynced) { - history.updateBestFullBlock(chain.last.header) - } - - // Until UTXO snapshot synchronization is implemented, we should always start to apply full blocks from genesis - val fullBlocksToApply = chain - - history = history.append(fullBlocksToApply.head.blockTransactions).get._1 - history = history.append(fullBlocksToApply.head.extension).get._1 - history.bestFullBlockOpt.get.header shouldBe fullBlocksToApply.head.header - } - - property("nextModifiersToDownload") { - var history = genHistory() - val chain = genChain(BlocksToKeep) - history = applyBlock(history, chain.head) - history.bestFullBlockOpt.value shouldBe chain.head - history = applyHeaderChain(history, HeaderChain(chain.map(_.header).tail)) - - val missedChain = chain.tail.toList - val missedBS = missedChain.flatMap { fb => - Seq((BlockTransactions.modifierTypeId, fb.blockTransactions.encodedId), (Extension.modifierTypeId, fb.extension.encodedId)) - }.foldLeft(Map.empty[NetworkObjectTypeId.Value, Seq[String]]) { case (newAcc, (mType, mId)) => - newAcc.adjust(mType)(_.fold(Seq(mId))(_ :+ mId)) - } - - history.nextModifiersToDownload(1, (_, id) => !history.contains(id)) - .map(id => (id._1, id._2.map(Algos.encode))) shouldEqual missedBS.mapValues(_.take(1)).view.force - - history.nextModifiersToDownload(2 * (BlocksToKeep - 1), (_, id) => !history.contains(id)) - .map(id => (id._1, id._2.map(Algos.encode))) shouldEqual missedBS - - history.nextModifiersToDownload(2, (_, id) => !history.contains(id) && (id != missedChain.head.blockTransactions.id)) - .map(id => (id._1, id._2.map(Algos.encode))) shouldEqual missedBS.mapValues(_.take(2).filter( _ != missedChain.head.blockTransactions.id)).view.force - } - - property("append header as genesis") { - val history = genHistory() - history.bestHeaderOpt shouldBe None - val header = genHeaderChain(1, history, diffBitsOpt = None, useRealTs = false).head - val updHistory = history.append(header).get._1 - updHistory.bestHeaderOpt shouldBe Some(header) - val restoredHeader = updHistory.modifierById(header.id) - restoredHeader shouldBe Some(header) - - val bytesFromSerializer = HeaderSerializer.toBytes(header) - val bytesFromDb = updHistory.modifierBytesById(header.id).get - bytesFromSerializer.sameElements(bytesFromDb) shouldBe true - } - - property("append header as genesis - via applyHeaderChain") { - val history = genHistory() - history.bestHeaderOpt shouldBe None - val header = genHeaderChain(1, history, diffBitsOpt = None, useRealTs = false).head - - val updHistory = applyHeaderChain(history, HeaderChain(Seq(header))) - updHistory.bestHeaderOpt shouldBe Some(header) - updHistory.modifierById(header.id) shouldBe Some(header) - } - - property("append header to genesis - 2") { - val (us, bh) = createUtxoState(settings) - - val block = validFullBlock(None, us, bh) - - val history = genHistory() - history.bestHeaderOpt shouldBe None - val header = block.header - - HeaderSerializer.parseBytes(HeaderSerializer.toBytes(header)) shouldBe header - - val actualHeader = history.append(header).get._1.bestHeaderOpt.value - actualHeader shouldBe header - } - - property("Appended headers and transactions blocks to best chain in tx history") { - var history = genHistory() - - history = applyChain(history, genChain(BlocksInChain, history)) - - genChain(BlocksInChain, history).tail.foreach { fullBlock => - val startFullBlock = history.bestFullBlockOpt.value - - val header = fullBlock.header - val txs = fullBlock.blockTransactions - val extension = fullBlock.extension - history.contains(header) shouldBe false - history.contains(txs) shouldBe false - history.contains(extension) shouldBe false - history.applicable(header) shouldBe true - history.applicable(txs) shouldBe false - history.applicable(extension) shouldBe false - - history = history.append(header).get._1 - - history.contains(header) shouldBe true - history.contains(txs) shouldBe false - history.contains(extension) shouldBe false - history.applicable(header) shouldBe false - history.applicable(txs) shouldBe true - history.applicable(extension) shouldBe true - history.bestHeaderOpt.value shouldBe header - - history.bestFullBlockOpt.value shouldBe startFullBlock - - history = history.append(txs).get._1 - history = history.append(extension).get._1 - - history.contains(header) shouldBe true - history.contains(txs) shouldBe true - history.contains(extension) shouldBe true - history.applicable(header) shouldBe false - history.applicable(txs) shouldBe false - history.applicable(extension) shouldBe false - history.bestHeaderOpt.value shouldBe header - history.bestFullBlockOpt.value.header shouldBe fullBlock.header - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala deleted file mode 100644 index a377e8a2e7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala +++ /dev/null @@ -1,452 +0,0 @@ -package org.ergoplatform.nodeView.history.extra - -import org.ergoplatform.ErgoBox.TokenId -import org.ergoplatform.ErgoLikeContext.Height -import org.ergoplatform._ -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.mining.{AutolykosPowScheme, CandidateBlock, CandidateGenerator} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree -import org.ergoplatform.nodeView.history.extra.SegmentSerializer.{boxSegmentId, txSegmentId} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.settings.{ErgoSettings, NetworkType, NipopowSettings, NodeConfigurationSettings, UtxoSettings} -import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestHelpers, HistoryTestHelpers} -import scorex.util.{ModifierId, bytesToId} -import sigmastate.Values -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigma.{Coll, Colls} -import spire.implicits.cfor - -import java.io.File -import scala.annotation.tailrec -import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer -import scala.concurrent.duration.{DurationInt, FiniteDuration} -import scala.reflect.ClassTag -import scala.util.{Random, Try} - -class ExtraIndexerSpecification extends ErgoPropertyTest with ExtraIndexerBase with HistoryTestHelpers { - - type ID_LL = mutable.HashMap[ModifierId,(Long,Long)] - - override protected val saveLimit: Int = 1 // save every block - override protected implicit val segmentTreshold: Int = 8 // split to smaller segments - override protected implicit val addressEncoder: ErgoAddressEncoder = initSettings.chainSettings.addressEncoder - - val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(StateType.Utxo, verifyTransactions = true, - -1, UtxoSettings(utxoBootstrap = false, 0, 2), NipopowSettings(nipopowBootstrap = false, 1), mining = false, - ChainGenerator.txCostLimit, ChainGenerator.txSizeLimit, useExternalMiner = false, internalMinersCount = 1, - internalMinerPollingInterval = 1.second, miningPubKeyHex = None, offlineGeneration = false, - 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, rebroadcastCount = 20, - 1000000, 100, adProofsSuffixLength = 112 * 1024, extraIndex = false) - - val HEIGHT: Int = 50 - val BRANCHPOINT: Int = HEIGHT / 2 - - def createDB(): Unit = { - val dir: File = createTempDir - dir.mkdirs() - - val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, initSettings.chainSettings, - nodeSettings, settings.scorexSettings, settings.walletSettings, settings.cacheSettings) - - _history = ErgoHistory.readOrGenerate(fullHistorySettings)(null) - - ChainGenerator.generate(HEIGHT, dir)(_history) - - // reset all variables - indexedHeight = 0 - globalTxIndex = 0L - globalBoxIndex = 0L - lastWroteToDB = 0 - caughtUp = false - rollback = false - general.clear() - boxes.clear() - trees.clear() - tokens.clear() - segments.clear() - } - - def manualIndex(limit: Int): (ID_LL, // address -> (erg,tokenSum) - ID_LL, // tokenId -> (boxesCount,_) - Int, // txs indexed - Int) = { // boxes indexed - var txsIndexed = 0 - var boxesIndexed = 0 - val addresses: ID_LL = mutable.HashMap[ModifierId,(Long,Long)]() - val indexedTokens: ID_LL = mutable.HashMap[ModifierId,(Long,Long)]() - cfor(1)(_ <= limit, _ + 1) { i => - _history.getReader.bestBlockTransactionsAt(i).get.txs.foreach { tx => - txsIndexed += 1 - if (i != 1) { - tx.inputs.foreach { input => - val iEb: IndexedErgoBox = _history.getReader.typedExtraIndexById[IndexedErgoBox](bytesToId(input.boxId)).get - val address = hashErgoTree(ExtraIndexer.getAddress(iEb.box.ergoTree)(addressEncoder).script) - val prev = addresses(address) - addresses.put(address, (prev._1 - iEb.box.value, prev._2 - iEb.box.additionalTokens.toArray.map(_._2).sum)) - } - } - tx.outputs.foreach { output => - boxesIndexed += 1 - val address = hashErgoTree(addressEncoder.fromProposition(output.ergoTree).get.script) - val prev = addresses.getOrElse(address, (0L, 0L)) - addresses.put(address, (prev._1 + output.value, prev._2 + output.additionalTokens.toArray.map(_._2).sum)) - cfor(0)(_ < output.additionalTokens.length, _ + 1) { j => - val token = IndexedToken.fromBox(new IndexedErgoBox(i, None, None, output, 0), j) - val prev2 = indexedTokens.getOrElse(token.id, (0L, 0L)) - indexedTokens.put(token.id, (prev2._1 + 1, 0)) - } - } - } - } - (addresses, indexedTokens, txsIndexed, boxesIndexed) - } - - def checkSegmentables[T <: Segment[_] : ClassTag](segmentables: ID_LL, - isChild: Boolean = false, - check: ((T, (Long, Long))) => Boolean - ): Int = { - var errors: Int = 0 - segmentables.foreach { segmentable => - history.typedExtraIndexById[T](segmentable._1) match { - case Some(obj: T) => - if(isChild) { // this is a segment - // check tx segments - val txSegments: ID_LL = mutable.HashMap.empty[ModifierId,(Long,Long)] - txSegments ++= (0 until obj.txSegmentCount).map(n => obj.idMod(txSegmentId(obj.parentId, n))).map(Tuple2(_, (0L, 0L))) - checkSegmentables(txSegments, isChild = true, check) shouldBe 0 - // check box segments - val boxSegments: ID_LL = mutable.HashMap.empty[ModifierId,(Long,Long)] - boxSegments ++= (0 until obj.boxSegmentCount).map(n => obj.idMod(boxSegmentId(obj.parentId, n))).map(Tuple2(_, (0L, 0L))) - checkSegmentables(boxSegments, isChild = true, check) shouldBe 0 - }else { // this is the parent object - // check properties of object - if(!check((obj, segmentable._2))) - errors += 1 - // check boxes in memory - obj.boxes.foreach { boxNum => - NumericBoxIndex.getBoxByNumber(history, boxNum) match { - case Some(iEb) => - if (iEb.isSpent) - boxNum.toInt should be <= 0 - else - boxNum.toInt should be >= 0 - case None => - System.err.println(s"Box $boxNum not found in database") - errors += 1 - } - } - // check txs in memory - obj.txs.foreach { txNum => - NumericTxIndex.getTxByNumber(history, txNum) shouldNot be(empty) - } - } - case None => - System.err.println(s"Segmentable object ${segmentable._1} should exist, but was not found") - errors += 1 - } - } - errors - } - - def checkAddresses(addresses: ID_LL): Int = - checkSegmentables[IndexedErgoAddress](addresses, isChild = false, seg => { - seg._1.balanceInfo.get.nanoErgs == seg._2._1 && seg._1.balanceInfo.get.tokens.map(_._2).sum == seg._2._2 - }) - - def checkTokens(indexedTokens: ID_LL): Int = - checkSegmentables[IndexedToken](indexedTokens, isChild = false, seg => { - seg._1.boxCount == seg._2._1 - }) - - property("extra indexer transactions") { - createDB() - run() - cfor(0)(_ < globalTxIndex, _ + 1) {n => - val id = history.typedExtraIndexById[NumericTxIndex](bytesToId(NumericTxIndex.indexToBytes(n))) - id shouldNot be(empty) - history.typedExtraIndexById[IndexedErgoTransaction](id.get.m) shouldNot be(empty) - } - } - - property("extra indexer boxes") { - createDB() - run() - cfor(0)(_ < globalBoxIndex, _ + 1) { n => - val id = history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(n))) - id shouldNot be(empty) - history.typedExtraIndexById[IndexedErgoBox](id.get.m) shouldNot be(empty) - } - } - - property("extra indexer addresses") { - createDB() - run() - val (addresses, _, _, _) = manualIndex(HEIGHT) - checkAddresses(addresses) shouldBe 0 - } - - property("extra indexer tokens") { - createDB() - run() - val (_, indexedTokens, _, _) = manualIndex(HEIGHT) - checkTokens(indexedTokens) shouldBe 0 - } - - property("extra indexer rollback") { - createDB() - - run() - - val txIndexBefore = globalTxIndex - val boxIndexBefore = globalBoxIndex - - // manually count balances - val (addresses, indexedTokens, txsIndexed, boxesIndexed) = manualIndex(BRANCHPOINT) - - // perform rollback - removeAfter(BRANCHPOINT) - - // address balances - checkAddresses(addresses) shouldBe 0 - - // token indexes - checkTokens(indexedTokens) shouldBe 0 - - // check indexnumbers - globalTxIndex shouldBe txsIndexed - globalBoxIndex shouldBe boxesIndexed - - // check txs - cfor(0)(_ < txIndexBefore, _ + 1) {txNum => - val txOpt = history.typedExtraIndexById[NumericTxIndex](bytesToId(NumericTxIndex.indexToBytes(txNum))) - if(txNum < globalTxIndex) - txOpt shouldNot be(empty) - else - txOpt shouldBe None - } - - // check boxes - cfor(0)(_ < boxIndexBefore, _ + 1) { boxNum => - val boxOpt = history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(boxNum))) - if (boxNum < globalBoxIndex) - boxOpt shouldNot be(empty) - else - boxOpt shouldBe None - } - - // ------------------------------------------------------------------- - // restart indexer to catch up - run() - - // Check addresses again - val (addresses2, indexedTokens2, _, _) = manualIndex(HEIGHT) - checkAddresses(addresses2) shouldBe 0 - checkTokens(indexedTokens2) shouldBe 0 - - // check indexnumbers again - globalTxIndex shouldBe txIndexBefore - globalBoxIndex shouldBe boxIndexBefore - - // check txs after caught up - cfor(0)(_ < txIndexBefore, _ + 1) { txNum => - history.typedExtraIndexById[NumericTxIndex](bytesToId(NumericTxIndex.indexToBytes(txNum))) shouldNot be(empty) - } - - // check boxes after caught up - cfor(0)(_ < boxIndexBefore, _ + 1) { boxNum => - history.typedExtraIndexById[NumericBoxIndex](bytesToId(NumericBoxIndex.indexToBytes(boxNum))) shouldNot be(empty) - } - - } - -} - -object ChainGenerator extends ErgoTestHelpers { - - val pow: AutolykosPowScheme = new AutolykosPowScheme(powScheme.k, powScheme.n) - val blockInterval: FiniteDuration = 2.minute - val EmissionTxCost: Long = 20000 - val MinTxAmount: Long = 2000000 - val RewardDelay: Int = initSettings.chainSettings.monetary.minerRewardDelay - val MaxTxsPerBlock: Int = 10 - val minerPk: ProveDlog = defaultProver.hdKeys.head.publicImage - val selfAddressScript: Values.ErgoTree = P2PKAddress(minerPk).script - val minerProp: Values.ErgoTree = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk) - val votingEpochLength: Height = votingSettings.votingLength - val protocolVersion: Byte = initSettings.chainSettings.protocolVersion - val minimalSuffix = 2 - val txCostLimit: Height = initSettings.nodeSettings.maxTransactionCost - val txSizeLimit: Height = initSettings.nodeSettings.maxTransactionSize - - var startTime: Long = 0 - - def generate(length: Int, dir: File)(history: ErgoHistory): Unit = { - val stateDir = new File(s"${dir.getAbsolutePath}/state") - stateDir.mkdirs() - val (state, _) = ErgoState.generateGenesisUtxoState(stateDir, initSettings) - System.out.println(s"Going to generate a chain at ${dir.getAbsolutePath} starting from ${history.bestFullBlockOpt}") - startTime = System.currentTimeMillis() - (blockInterval * (length - 1)).toMillis - val chain = loop(state, None, None, Seq())(history) - System.out.println(s"Chain of length ${chain.length} generated") - history.bestHeaderOpt shouldBe history.bestFullBlockOpt.map(_.header) - history.bestFullBlockOpt.get.id shouldBe chain.last - System.out.println("History was generated successfully") - } - - @tailrec - private def loop(state: UtxoState, - initBox: Option[ErgoBox], - last: Option[Header], - acc: Seq[ModifierId])(history: ErgoHistory): Seq[ModifierId] = { - val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime) - if (time < System.currentTimeMillis()) { - val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight), - initBox, state.stateContext) - - val candidate = genCandidate(defaultProver.hdPubKeys.head.key, last, time, txs, state)(history) - val block = proveCandidate(candidate.get) - - history.append(block.header).get - block.blockSections.foreach(s => if (!history.contains(s)) history.append(s).get) - - val outToPassNext = if (last.isEmpty) { - block.transactions.flatMap(_.outputs).find(_.ergoTree == minerProp) - } else { - lastOut - } - - assert(outToPassNext.isDefined) - - log.info( - s"Block ${block.id} with ${block.transactions.size} transactions at height ${block.header.height} generated") - - loop(state.applyModifier(block, None)(_ => ()).get, outToPassNext, Some(block.header), acc :+ block.id)(history) - } else { - acc - } - } - - private def moveTokens(inOpt: Option[ErgoBox], cond: Boolean): Coll[(TokenId, Long)] = { - val tokens: ArrayBuffer[(TokenId, Long)] = ArrayBuffer.empty[(TokenId, Long)] - inOpt match { - case Some(input) if cond => - tokens += Tuple2(input.id.toTokenId, math.abs(Random.nextInt())) - case Some(tokenBox) if !cond => - tokenBox.additionalTokens.toArray.foreach(tokens += _) - case _ => - } - Colls.fromArray(tokens.toArray) - } - - private def genTransactions(height: Height, - inOpt: Option[ErgoBox], - ctx: ErgoStateContext): (Seq[ErgoTransaction], Option[ErgoBox]) = { - inOpt - .find { bx => - val canUnlock = (bx.creationHeight + RewardDelay <= height) || (bx.ergoTree != minerProp) - canUnlock && bx.ergoTree != initSettings.chainSettings.monetary.emissionBoxProposition && bx.value >= MinTxAmount - } - .map { input => - val qty = MaxTxsPerBlock - val amount = input.value - val outs = (0 until qty).map(i => new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(inOpt, i == 0))) - var i = 0 - val x = outs - .foldLeft((Seq.empty[ErgoTransaction], input)) { case ((acc, in), out) => - val inputs = IndexedSeq(in) - val newOut = - if (i > 0) - new ErgoBoxCandidate(amount, selfAddressScript, height, moveTokens(acc.lastOption.map(_.outputs.head), cond = false)) - else - out - val unsignedTx = UnsignedErgoTransaction(inputs.map(box => new UnsignedInput(box.id)), IndexedSeq(newOut)) - i += 1 - defaultProver.sign(unsignedTx, inputs, emptyDataBoxes, ctx) - .fold(_ => acc -> in, tx => (acc :+ ErgoTransaction(tx)) -> unsignedTx.outputs.head) - } - ._1 - (x, Some(x.last.outputs.head)) - } - .getOrElse(Seq.empty -> inOpt) - } - - private def genCandidate(minerPk: ProveDlog, - lastHeaderOpt: Option[Header], - ts: Long, - txsFromPool: Seq[ErgoTransaction], - state: UtxoStateReader)(history: ErgoHistory): Try[CandidateBlock] = Try { - val stateContext = state.stateContext - val nBits: Long = lastHeaderOpt - .map(parent => history.requiredDifficultyAfter(parent)) - .map(d => DifficultySerializer.encodeCompactBits(d)) - .getOrElse(settings.chainSettings.initialNBits) - - val interlinks = lastHeaderOpt - .flatMap { h => - history.typedModifierById[Extension](h.extensionId) - .flatMap(ext => NipopowAlgos.unpackInterlinks(ext.fields).toOption) - .map(nipopowAlgos.updateInterlinks(h, _)) - } - .getOrElse(Seq.empty) - val interlinksExtension = nipopowAlgos.interlinksToExtension(interlinks) - - val (extensionCandidate, votes: Array[Byte], version: Byte) = lastHeaderOpt.map { header => - val newHeight = header.height + 1 - val currentParams = stateContext.currentParameters - val betterVersion = protocolVersion > header.version - val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight - .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) - val forkVotingAllowed = votingFinishHeight.forall(fh => newHeight < fh) - val forkOrdered = settings.votingTargets.softFork != 0 - val voteForFork = betterVersion && forkOrdered && forkVotingAllowed - - if (newHeight % votingEpochLength == 0 && newHeight > 0) { - val (newParams, _) = currentParams.update(newHeight, voteForFork, stateContext.votingData.epochVotes, emptyVSUpdate, votingSettings) - (newParams.toExtensionCandidate ++ interlinksExtension, - newParams.suggestVotes(settings.votingTargets.targets, voteForFork), - newParams.blockVersion) - } else { - (nipopowAlgos.interlinksToExtension(interlinks), - currentParams.vote(settings.votingTargets.targets, stateContext.votingData.epochVotes, voteForFork), - currentParams.blockVersion) - } - }.getOrElse((interlinksExtension, Array(0: Byte, 0: Byte, 0: Byte), Header.InitialVersion)) - - val emissionTxOpt = CandidateGenerator.collectEmission(state, minerPk, emptyStateContext) - val txs = emissionTxOpt.toSeq ++ txsFromPool - - state.proofsForTransactions(txs).map { case (adProof, adDigest) => - CandidateBlock(lastHeaderOpt, version, nBits, adDigest, adProof, txs, ts, extensionCandidate, votes) - } - }.flatten - - @tailrec - private def proveCandidate(candidate: CandidateBlock): ErgoFullBlock = { - log.info(s"Trying to prove block with parent ${candidate.parentOpt.map(_.encodedId)} and timestamp ${candidate.timestamp}") - - pow.proveCandidate(candidate, defaultProver.hdKeys.head.privateInput.w) match { - case Some(fb) => fb - case _ => - val interlinks = candidate.parentOpt - .map(nipopowAlgos.updateInterlinks(_, NipopowAlgos.unpackInterlinks(candidate.extension.fields).get)) - .getOrElse(Seq.empty) - val minerTag = scorex.utils.Random.randomBytes(Extension.FieldKeySize) - proveCandidate { - candidate.copy( - extension = ExtensionCandidate(Seq(Array(0: Byte, 2: Byte) -> minerTag)) ++ nipopowAlgos.interlinksToExtension(interlinks) - ) - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala deleted file mode 100644 index 7020d1fee7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala +++ /dev/null @@ -1,41 +0,0 @@ -package org.ergoplatform.nodeView.history.storage - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.modifiers.history.ADProofs -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.HistoryTestHelpers -import org.scalacheck.Gen -import scorex.db.ByteArrayWrapper -import scorex.util.{ModifierId, idToBytes} - -class HistoryStorageSpec extends HistoryTestHelpers { - - val db = HistoryStorage(settings) - - property("Write Read Remove") { - val headers: Array[Header] = Gen.listOfN(20, defaultHeaderGen).sample.get.toArray - val modifiers: Array[ADProofs] = Gen.listOfN(20, randomADProofsGen).sample.get.toArray - def validityKey(id: ModifierId) = ByteArrayWrapper(Algos.hash("validity".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id))) - val indexes = headers.flatMap(h => Array(validityKey(h.id) -> Array(1.toByte))) - db.insert(indexes, (headers ++ modifiers).asInstanceOf[Array[BlockSection]]) shouldBe 'success - - headers.forall(h => db.contains(h.id)) shouldBe true - modifiers.forall(m => db.contains(m.id)) shouldBe true - - headers.forall(h => db.get(h.id).exists(_.nonEmpty)) shouldBe true - modifiers.forall(m => db.get(m.id).exists(_.nonEmpty)) shouldBe true - indexes.forall(i => db.getIndex(i._1).exists(_.nonEmpty)) shouldBe true - - db.remove(indexes.map(_._1), headers.map(_.id) ++ modifiers.map(_.id)) - - headers.forall(h => !db.contains(h.id)) shouldBe true - modifiers.forall(m => !db.contains(m.id)) shouldBe true - - headers.forall(h => !db.get(h.id).exists(_.nonEmpty)) shouldBe true - modifiers.forall(m => !db.get(m.id).exists(_.nonEmpty)) shouldBe true - indexes.forall(i => !db.getIndex(i._1).exists(_.nonEmpty)) shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala deleted file mode 100644 index 38aaa799d3..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala +++ /dev/null @@ -1,398 +0,0 @@ -package org.ergoplatform.nodeView.mempool - -import org.ergoplatform.{ErgoBoxCandidate, Input} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.ErgoTestHelpers -import org.ergoplatform.utils.generators.ErgoGenerators -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigmastate.Values.{ByteArrayConstant, TrueLeaf} -import sigmastate.interpreter.{ContextExtension, ProverResult} - -class ErgoMemPoolSpec extends AnyFlatSpec - with ErgoGenerators - with ErgoTestHelpers - with ScalaCheckPropertyChecks { - - it should "accept valid transaction" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val txs = validTransactionsFromUtxoState(wus) - val pool0 = ErgoMemPool.empty(settings) - val poolAfter = txs.foldLeft(pool0) { case (pool, tx) => - val (p, outcome) = pool.process(UnconfirmedTransaction(tx, None), us) - if (!outcome.isInstanceOf[ProcessingOutcome.Accepted]) { - throw new Exception("Transaction not accepted") - } - p - } - poolAfter.spentInputs.size shouldBe txs.flatMap(_.inputs).size - - // light mode - val poolLight = ErgoMemPool.empty(lightModeSettings) - txs.foreach { tx => - poolLight.process(UnconfirmedTransaction(tx, None), us)._2.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - } - } - - it should "respect given sorting order" in { - implicit val ms = settings.chainSettings.monetary - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val inputBox = wus.takeBoxes(1).head - val feeOut = new ErgoBoxCandidate(inputBox.value, feeProp, creationHeight = 0) - val tx = ErgoTransaction( - IndexedSeq(new Input(inputBox.id, ProverResult.empty)), - IndexedSeq(feeOut) - ) - - // Randomly initialized - settings.nodeSettings.mempoolSorting should (be (SortingOption.FeePerByte) or be (SortingOption.FeePerCycle)) - - val sortBySizeSettings: ErgoSettings = settings.copy( - nodeSettings = settings.nodeSettings.copy( - mempoolSorting = SortingOption.FeePerByte, - )) - - var poolSize = ErgoMemPool.empty(sortBySizeSettings) - poolSize = poolSize.process(UnconfirmedTransaction(tx, None), wus)._1 - val size = tx.size - poolSize.pool.orderedTransactions.firstKey.weight shouldBe OrderedTxPool.weighted(tx, size).weight - - val sortByCostSettings: ErgoSettings = settings.copy( - nodeSettings = settings.nodeSettings.copy( - mempoolSorting = SortingOption.FeePerCycle, - )) - - var poolCost = ErgoMemPool.empty(sortByCostSettings) - poolCost = poolCost.process(UnconfirmedTransaction(tx, None), wus)._1 - val validationContext = wus.stateContext.simplifiedUpcoming() - val cost = wus.validateWithCost(tx, validationContext, Int.MaxValue, None).get - poolCost.pool.orderedTransactions.firstKey.weight shouldBe OrderedTxPool.weighted(tx, cost).weight - } - - it should "decline already contained transaction" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val txs = validTransactionsFromUtxoState(wus) - var pool = ErgoMemPool.empty(settings) - txs.foreach { tx => - pool = pool.put(UnconfirmedTransaction(tx, None)) - } - txs.foreach { tx => - pool.process(UnconfirmedTransaction(tx, None), us)._2.isInstanceOf[ProcessingOutcome.Declined] shouldBe true - } - } - - it should "reject double-spending transaction if it is paying no more than one already sitting in the pool" in { - forAll(smallPositiveInt, smallPositiveInt) { case (n1, n2) => - whenever(n1 != n2) { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, extendedParameters).applyModifier(genesis)(_ => ()).get - - val feeProp = settings.chainSettings.monetary.feeProposition - val inputBox = wus.takeBoxes(100).collectFirst{ - case box if box.ergoTree == TrueLeaf.toSigmaProp.treeWithSegregation => box - }.get - val feeOut = new ErgoBoxCandidate(inputBox.value, feeProp, creationHeight = 0) - - def rndContext(n: Int): ContextExtension = ContextExtension(Map( - (1: Byte) -> ByteArrayConstant(Array.fill(1 + n)(0: Byte))) - ) - - val tx1Like = ErgoTransaction( - IndexedSeq(new Input(inputBox.id, new ProverResult(Array.emptyByteArray, rndContext(n1)))), - IndexedSeq(feeOut) - ) - - val tx2Like = ErgoTransaction( - IndexedSeq(new Input(inputBox.id, new ProverResult(Array.emptyByteArray, rndContext(n2)))), - IndexedSeq(feeOut) - ) - - val tx1 = UnconfirmedTransaction(ErgoTransaction(tx1Like.inputs, tx1Like.outputCandidates), None) - val tx2 = UnconfirmedTransaction(ErgoTransaction(ErgoTransaction(tx2Like.inputs, tx2Like.outputCandidates)), None) - - val pool0 = ErgoMemPool.empty(settings) - val (pool, tx1Outcome) = pool0.process(tx1, us) - - tx1Outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - - // tx1 and tx2 are spending the same input, and paying the same fee. - // So if tx2 is about a bigger or equal size, it should be rejected as it is paying less for a byte. - // Otherwise, tx2 is paying more for a byte and then it is replacing tx1. - if (tx2.transaction.size >= tx1.transaction.size) { - pool.process(tx2, us)._2.isInstanceOf[ProcessingOutcome.DoubleSpendingLoser] shouldBe true - } else { - val (updPool, outcome) = pool.process(tx2, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - updPool.size shouldBe 1 - updPool.take(1).head.transaction.id shouldBe tx2.transaction.id - } - } - } - } - - it should "decline transactions invalidated earlier" in { - val us = createUtxoState(settings)._1 - var pool = ErgoMemPool.empty(settings) - forAll(invalidBlockTransactionsGen) { blockTransactions => - val unconfirmedTxs = blockTransactions.txs.map(tx => UnconfirmedTransaction(tx, None)) - unconfirmedTxs.foreach(tx => pool = pool.process(tx, us)._1) - unconfirmedTxs.foreach(tx => - pool.process(tx, us)._2.isInstanceOf[ProcessingOutcome.Declined] shouldBe true) - } - } - - it should "decline transactions not meeting min fee" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val txs = validTransactionsFromUtxoState(wus) - val unconfirmedTxs = txs.map(tx => UnconfirmedTransaction(tx, None)) - - val maxSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(minimalFeeAmount = Long.MaxValue)) - val pool = ErgoMemPool.empty(maxSettings) - unconfirmedTxs.foreach { tx => - val (_, outcome) = pool.process(tx, us) - outcome.isInstanceOf[ProcessingOutcome.Declined] shouldBe true - outcome.asInstanceOf[ProcessingOutcome.Declined] - .e.getMessage.contains("Min fee not met") shouldBe true - } - - val minSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(minimalFeeAmount = 0)) - val pool2 = ErgoMemPool.empty(minSettings) - unconfirmedTxs.foreach { tx => - val (_, outcome) = pool2.process(tx, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - } - } - - it should "invalidate or reject invalid transaction" in { - val us = createUtxoState(settings)._1 - val pool = ErgoMemPool.empty(settings) - forAll(invalidBlockTransactionsGen) { blockTransactions => - blockTransactions.txs.forall{tx => - val valRes = pool.process(UnconfirmedTransaction(tx, None), us)._2 - valRes.isInstanceOf[ProcessingOutcome.Invalidated] || - valRes.isInstanceOf[ProcessingOutcome.Declined]} shouldBe true - } - } - - it should "accept only unique transactions" in { - val pool = ErgoMemPool.empty(settings) - val tx = UnconfirmedTransaction(invalidErgoTransactionGen.sample.get, None) - pool.put(Seq(tx, tx, tx)).size shouldBe 1 - } - - it should "drop less prioritized transaction in case of pool overflow" in { - val limitedPoolSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(mempoolCapacity = 4)) - var pool = ErgoMemPool.empty(limitedPoolSettings) - val masterTx = invalidErgoTransactionGen.sample.get - val proposition = settings.chainSettings.monetary.feeProposition - val txsWithAscendingPriority = (0 to 4).foldLeft(Seq.empty[ErgoTransaction]) { case (acc, idx) => - val c = masterTx.outputCandidates.head - acc :+ masterTx.copy(outputCandidates = IndexedSeq( - new ErgoBoxCandidate(idx * 10000 + 1, proposition, c.creationHeight, c.additionalTokens, c.additionalRegisters))) - } - val lessPrioritizedTxs = txsWithAscendingPriority.init.map(tx => UnconfirmedTransaction(tx, None)) - val mostPrioritizedTx = UnconfirmedTransaction(txsWithAscendingPriority.last, None) - pool = pool.put(lessPrioritizedTxs) - - pool.size shouldBe 4 - pool.getAll should contain only (lessPrioritizedTxs: _*) - pool = pool.put(Seq(mostPrioritizedTx)) - pool.size shouldBe 4 - pool.getAll should contain only (mostPrioritizedTx +: lessPrioritizedTxs.tail: _*) - } - - it should "Accept output of pooled transactions" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val txs = validTransactionsFromUtxoState(wus).map(tx => UnconfirmedTransaction(tx, None)) - var pool = ErgoMemPool.empty(settings) - txs.foreach { tx => - pool = pool.put(tx) - } - txs.foreach { tx => - val spendingBox = tx.transaction.outputs.head - val unconfirmedTransaction = UnconfirmedTransaction(tx.transaction.copy( - inputs = IndexedSeq(new Input(spendingBox.id, emptyProverResult)), - outputCandidates = IndexedSeq(spendingBox)), None) - val (newPool, outcome) = pool.process(unconfirmedTransaction, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - pool = newPool - } - } - - it should "consider families for replacement policy" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - var txs = validTransactionsFromUtxoState(wus).map(tx => UnconfirmedTransaction(tx, None)) - val family_depth = 10 - val limitedPoolSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(mempoolCapacity = (family_depth + 1) * txs.size)) - var pool = ErgoMemPool.empty(limitedPoolSettings) - txs.foreach { tx => - pool = pool.put(tx) - } - for (_ <- 1 to family_depth) { - txs = txs.map(tx => { - val spendingBox = tx.transaction.outputs.head - val newTx = UnconfirmedTransaction(tx.transaction.copy(inputs = IndexedSeq(new Input(spendingBox.id, emptyProverResult)), - outputCandidates = IndexedSeq(spendingBox)), None) - val (newPool, outcome) = pool.process(newTx, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - pool = newPool - newTx - }) - } - pool.size shouldBe (family_depth + 1) * txs.size - txs.foreach { utx => - val tx = utx.transaction - val sb = tx.outputs.head - val txToDecline = tx.copy(inputs = IndexedSeq(new Input(sb.id, emptyProverResult)), - outputCandidates = IndexedSeq(new ErgoBoxCandidate(sb.value, sb.ergoTree, sb.creationHeight, sb.additionalTokens, sb.additionalRegisters))) - val res = pool.process(UnconfirmedTransaction(txToDecline, None), us)._2 - res.isInstanceOf[ProcessingOutcome.Declined] shouldBe true - res.asInstanceOf[ProcessingOutcome.Declined].e.getMessage.contains("pays less") shouldBe true - pool.size shouldBe (family_depth + 1) * txs.size - } - } - - it should "correctly remove transaction from pool and rebuild families" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - var txs = validTransactionsFromUtxoState(wus).map(tx => UnconfirmedTransaction(tx, None)) - var allTxs = txs - val family_depth = 10 - val limitedPoolSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(mempoolCapacity = (family_depth + 1) * txs.size)) - var pool = ErgoMemPool.empty(limitedPoolSettings) - txs.foreach { tx => - pool = pool.put(tx) - } - for (_ <- 1 to family_depth) { - txs = txs.map(tx => { - val spendingBox = tx.transaction.outputs.head - val newTx = UnconfirmedTransaction(tx.transaction.copy(inputs = IndexedSeq(new Input(spendingBox.id, emptyProverResult)), - outputCandidates = IndexedSeq(spendingBox)), None) - val (newPool, outcome) = pool.process(newTx, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - pool = newPool - allTxs = allTxs :+ newTx - newTx - }) - } - pool.size shouldBe (family_depth + 1) * txs.size - allTxs.foreach { tx => - pool = pool.remove(tx.transaction) - } - pool.size shouldBe 0 - } - - it should "return results take / getAll / getAllPrioritized sorted by priority" in { - val feeProp = settings.chainSettings.monetary.feeProposition - - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - var txs = validTransactionsFromUtxoState(wus).map(tx => UnconfirmedTransaction(tx, None)) - val family_depth = 10 - val limitedPoolSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(mempoolCapacity = (family_depth + 1) * txs.size)) - var pool = ErgoMemPool.empty(limitedPoolSettings) - txs.foreach { tx => - pool = pool.put(tx) - } - for (_ <- 1 to family_depth) { - txs = txs.map(tx => { - val spendingBox = tx.transaction.outputs.head - - val sc = spendingBox.toCandidate - val out0 = new ErgoBoxCandidate(sc.value - 55000, sc.ergoTree, sc.creationHeight) - val out1 = new ErgoBoxCandidate(55000, feeProp, sc.creationHeight) - - val newTx = UnconfirmedTransaction(tx.transaction.copy(inputs = IndexedSeq(new Input(spendingBox.id, emptyProverResult)), - outputCandidates = IndexedSeq(out0, out1)), None) - val (newPool, outcome) = pool.process(newTx, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - pool = newPool - newTx - }) - } - - val weights = pool.weightedTransactionIds(11) - val ids = weights.map(_.id) - - pool.take(11).toSeq.map(_.transaction.id) shouldBe ids - pool.getAll.map(_.transaction.id) shouldBe ids - pool.getAllPrioritized.map(_.transaction.id) shouldBe ids - - val conformingTxs = pool.take(3).toSeq - val stateWithTxs = wus.withUnconfirmedTransactions(conformingTxs) - - conformingTxs.map(_.transaction).flatMap(_.inputs).map(_.boxId).forall(bIb => stateWithTxs.boxById(bIb) - .isDefined) shouldBe true - } - - it should "add removed transaction to mempool statistics" in { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(None, us, bh) - val wus = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - var txs = validTransactionsFromUtxoState(wus).map(tx => UnconfirmedTransaction(tx, None)) - var allTxs = txs - val family_depth = 10 - val limitedPoolSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(mempoolCapacity = (family_depth + 1) * txs.size)) - var pool = ErgoMemPool.empty(limitedPoolSettings) - txs.foreach { tx => - pool = pool.put(tx) - } - for (_ <- 1 to family_depth) { - txs = txs.map(tx => { - val spendingBox = tx.transaction.outputs.head - val newTx = UnconfirmedTransaction(tx.transaction.copy(inputs = IndexedSeq(new Input(spendingBox.id, emptyProverResult)), - outputCandidates = IndexedSeq(spendingBox)), None) - val (newPool, outcome) = pool.process(newTx, us) - outcome.isInstanceOf[ProcessingOutcome.Accepted] shouldBe true - pool = newPool - allTxs = allTxs :+ newTx - newTx - }) - } - pool.size shouldBe (family_depth + 1) * txs.size - pool.stats.histogram shouldBe MemPoolStatistics(System.currentTimeMillis(),0,System.currentTimeMillis()).histogram - pool.stats.takenTxns shouldBe MemPoolStatistics(System.currentTimeMillis(),0,System.currentTimeMillis()).takenTxns - pool.stats.snapTakenTxns shouldBe MemPoolStatistics(System.currentTimeMillis(),0,System.currentTimeMillis()).snapTakenTxns - - allTxs.foreach { tx => - pool = pool.remove(tx.transaction) - } - pool.size shouldBe 0 - pool.stats.takenTxns shouldBe (family_depth + 1) * txs.size - } - - it should "put not adding transaction twice" in { - val pool = ErgoMemPool.empty(settings).pool - val tx = invalidErgoTransactionGen.sample.get - val now = System.currentTimeMillis() - - val utx1 = new UnconfirmedTransaction(tx, None, now, now, None, None) - val utx2 = new UnconfirmedTransaction(tx, None, now, now, None, None) - val utx3 = new UnconfirmedTransaction(tx, None, now + 1, now + 1, None, None) - val updPool = pool.put(utx1, 100).remove(utx1).put(utx2, 500).put(utx3, 5000) - updPool.size shouldBe 1 - updPool.get(utx3.id).get.lastCheckedTime shouldBe (now + 1) - } - -} - - diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ExpiringApproximateCacheSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ExpiringApproximateCacheSpec.scala deleted file mode 100644 index fac02822a2..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ExpiringApproximateCacheSpec.scala +++ /dev/null @@ -1,98 +0,0 @@ -package org.ergoplatform.nodeView.mempool - -import org.scalactic.TripleEqualsSupport -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import java.util.UUID -import scala.concurrent.duration._ - -class ExpiringApproximateCacheSpec - extends AnyFlatSpec - with Matchers - with TripleEqualsSupport { - - it should "behave as fixed sized FIFO collection of bloom filters" in { - val cache = ExpiringApproximateCache.empty( - frontCacheSize = 100, - frontCacheExpiration = 1.hour - ) - cache.bloomFilterQueueSize shouldBe 4 - val fullCache = - (1 to 500).map(_.toString).foldLeft(cache) { case (acc, n) => acc.put(n) } - - (1 to 400).foreach { n => - assert(fullCache.mightContain(n.toString), s"$n should be in bloom filter") - } - - println("size: " + fullCache.bloomFilterQueue.size) - - fullCache.bloomFilterQueue.size shouldBe 4 - assert( - fullCache.approximateElementCount > 430, - "At least 430 elements must be present" - ) - - // add some more elements over limit - val newCache = - (501 to 1000).map(_.toString).foldLeft(fullCache) { case (acc, n) => acc.put(n) } - newCache.bloomFilterQueue.size shouldBe 4 - assert(newCache.approximateElementCount < 570, "Max 600 elements must be present") - - (601 to 800).foreach { n => - assert(newCache.mightContain(n.toString), s"$n should be in bloom filter") - } - } - - it should "have a fixed size expiring cache before bloom filters" in { - val cache = ExpiringApproximateCache.empty( - frontCacheSize = 100, - frontCacheExpiration = 50.millis - ) - // let's add 100 elems directly to front cache - val fullCache = - (1 to 100).map(_.toString).foldLeft(cache) { case (acc, n) => acc.put(n) } - - (1 to 100).foreach { n => - assert(fullCache.mightContain(n.toString), s"$n should be in front cache") - } - fullCache.frontCache.size shouldBe 100 - // now let's add another element which won't with to front cache so it goes to bloom filters - val updatedCache = fullCache.put("101") - updatedCache.frontCache.size shouldBe 1 - updatedCache.frontCache.contains("101") shouldBe true - assert(updatedCache.mightContain("100"), s"100 should be in bloom filter") - - val expiringCache = (102 to 200).map(_.toString).foldLeft(updatedCache) { case (acc, n) => - acc.put(n) - } - - expiringCache.frontCache.size shouldBe 100 - - // test that all elements in front cache expire - Thread.sleep(200) - val expriredCache = expiringCache.put("201") - expriredCache.frontCache.size shouldBe 1 - // expired elements are not in the filters as well - val fp = (102 to 200).map(_.toString).count(expriredCache.mightContain) - (fp < 5) shouldBe true // no more than 5% false positives, with some extra buffer given - } - - it should "overflow properly" in { - val cache = ExpiringApproximateCache.empty( - frontCacheSize = 10000, - frontCacheExpiration = 1.hour - ) - // let's add 2M of realistic elems to cache - val elemCount = 2000000 - val uuids = (1 to elemCount).map(_ => UUID.randomUUID().toString) - val fullCache = uuids.foldLeft(cache) { case (acc, n) => acc.put(n) } - - uuids.forall(fullCache.mightContain) shouldBe false - uuids.takeRight(10000).forall(fullCache.mightContain) shouldBe true // last elements there - // first ids forgotten, except of false positives (with some buffer we add) - val fp = uuids.take(10000).count(id => fullCache.mightContain(id)) - (fp < 100) shouldBe true // we allow up to 1% false positives - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala deleted file mode 100644 index 7f2f6b7cca..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/mempool/ScriptsSpec.scala +++ /dev/null @@ -1,81 +0,0 @@ -package org.ergoplatform.nodeView.mempool - -import org.ergoplatform.ErgoAddressEncoder.TestnetNetworkPrefix -import org.ergoplatform.ErgoTreePredef.boxCreationHeight -import org.ergoplatform.nodeView.state.{BoxHolder, ErgoState, UtxoState} -import org.ergoplatform.settings.Algos -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.{ErgoBox, ErgoTreePredef, Height, Self} -import scorex.crypto.authds.avltree.batch.Remove -import sigmastate.Values._ -import sigmastate._ -import sigmastate.crypto.CryptoConstants.dlogGroup -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval.{CompiletimeIRContext, IRContext} -import sigmastate.lang.Terms._ -import sigmastate.lang.{CompilerSettings, SigmaCompiler, TransformingSigmaBuilder} - -import scala.util.Try - -class ScriptsSpec extends ErgoPropertyTest { - - val compiler = SigmaCompiler( - CompilerSettings(TestnetNetworkPrefix, TransformingSigmaBuilder, lowerMethodCalls = true) - ) - val delta = emission.settings.minerRewardDelay - val fixedBox: ErgoBox = ergoBoxGen(fromString("1 == 1"), heightGen = 0).sample.get - implicit lazy val context: IRContext = new CompiletimeIRContext - - property("simple operations without cryptography") { - // true/false - applyBlockSpendingScript(Values.TrueLeaf.toSigmaProp) shouldBe 'success - applyBlockSpendingScript(Values.FalseLeaf.toSigmaProp) shouldBe 'failure - // eq - applyBlockSpendingScript(EQ(IntConstant(1), IntConstant(1)).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(EQ(IntConstant(1), IntConstant(2)).toSigmaProp) shouldBe 'failure - // math - applyBlockSpendingScript(EQ(Plus(1, 2), Minus(6, 3)).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(EQ(Multiply(1, 2), Divide(7, 3)).toSigmaProp) shouldBe 'success - // context - applyBlockSpendingScript(EQ(IntConstant(1), Height).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(fromString("CONTEXT.preHeader.height == 1")) shouldBe 'success - applyBlockSpendingScript(fromString("CONTEXT.headers.size == 0")) shouldBe 'success - applyBlockSpendingScript(fromString(s"CONTEXT.dataInputs.exists{ (box: Box) => box.value == ${fixedBox.value}L}")) shouldBe 'success - // todo other common operations: tokens, data from registers, context extension, etc. - } - - property("simple crypto") { - applyBlockSpendingScript(defaultMinerPk) shouldBe 'success - applyBlockSpendingScript(SigmaAnd(defaultProver.hdKeys.map(s => SigmaPropConstant(s.publicImage)))) shouldBe 'success - applyBlockSpendingScript(SigmaAnd(defaultMinerPk, ProveDlog(dlogGroup.generator))) shouldBe 'failure - applyBlockSpendingScript(SigmaOr(defaultMinerPk, ProveDlog(dlogGroup.generator))) shouldBe 'success - } - - property("predef scripts") { - delta shouldBe -1000 - - applyBlockSpendingScript(GE(Height, Plus(boxCreationHeight(Self), IntConstant(delta))).toSigmaProp) shouldBe 'success - applyBlockSpendingScript(ErgoTreePredef.rewardOutputScript(delta, defaultMinerPk)) shouldBe 'success -// applyBlockSpendingScript(ErgoScriptPredef.feeProposition(delta)) shouldBe 'success - } - - - private def fromString(str: String): ErgoTree = { - compiler.compile(Map(), str).buildTree.asBoolValue.toSigmaProp - } - - private def applyBlockSpendingScript(script: ErgoTree): Try[UtxoState] = { - val scriptBox = ergoBoxGen(script, heightGen = 0).sample.get - val bh = BoxHolder(Seq(fixedBox, scriptBox)) - val us = UtxoState.fromBoxHolder(bh, None, createTempDir, settings, parameters) - bh.boxes.map(b => us.boxById(b._2.id) shouldBe Some(b._2)) - val tx = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(1)), 201)._1 - tx.size shouldBe 1 - tx.head.inputs.size shouldBe 2 - ErgoState.boxChanges(tx).get._1.foreach { case Remove(boxId) => - assert(us.boxById(boxId).isDefined, s"Box ${Algos.encode(boxId)} missed") - } - val block = validFullBlock(None, us, tx, Some(1234L)) - us.applyModifier(block, None)(_ => ()) - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala deleted file mode 100644 index 7cf71def1a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/DigestStateSpecification.scala +++ /dev/null @@ -1,134 +0,0 @@ -package org.ergoplatform.nodeView.state - -import org.ergoplatform.{DataInput, Input} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.ADProofs -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import scorex.core._ -import scorex.crypto.authds.ADDigest -import sigmastate.interpreter.ProverResult - -class DigestStateSpecification extends ErgoPropertyTest { - - private val emptyVersion: VersionTag = bytesToVersion(Array.fill(32)(0: Byte)) - private val emptyAdDigest: ADDigest = ADDigest @@ Array.fill(32)(0: Byte) - - property("reopen") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - - val fb = validFullBlock(parentOpt = None, us, bh) - val dir2 = createTempDir - val ds = DigestState.create(Some(us.version), Some(us.rootDigest), dir2, settings) - ds.applyModifier(fb, None)(_ => ()) shouldBe 'success - ds.close() - - val state = DigestState.create(None, None, dir2, settings) - state.version shouldEqual fb.header.id - state.rootDigest shouldEqual fb.header.stateRoot - } - } - - property("validate() - valid block") { - var (us, bh) = createUtxoState(settings) - var ds = createDigestState(us.version, us.rootDigest) - var parentOpt: Option[ErgoFullBlock] = None - - forAll { seed: Int => - val blBh = validFullBlockWithBoxHolder(parentOpt, us, bh, new RandomWrapper(Some(seed))) - val block = blBh._1 - bh = blBh._2 - ds = ds.applyModifier(block, None)(_ => ()).get - us = us.applyModifier(block, None)(_ => ()).get - parentOpt = Some(block) - } - } - - property("validate() - invalid block") { - forAll(invalidErgoFullBlockGen) { b => - val state = createDigestState(emptyVersion, emptyAdDigest) - state.validate(b).isFailure shouldBe true - } - } - - property("applyModifier() - valid block") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - - val block = validFullBlock(parentOpt = None, us, bh) - block.blockTransactions.transactions.exists(_.dataInputs.nonEmpty) shouldBe true - - val ds = createDigestState(us.version, us.rootDigest) - ds.applyModifier(block, None)(_ => ()) shouldBe 'success - } - } - - property("applyModifier() - invalid block") { - forAll(invalidErgoFullBlockGen) { b => - val state = createDigestState(emptyVersion, emptyAdDigest) - state.applyModifier(b, None)(_ => ()).isFailure shouldBe true - } - } - - property("rollback & rollback versions") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - - val block = validFullBlock(parentOpt = None, us, bh) - - val ds = createDigestState(us.version, us.rootDigest) - - ds.rollbackVersions.size shouldEqual 1 - - val ds2 = ds.applyModifier(block, None)(_ => ()).get - - ds2.rollbackVersions.size shouldEqual 2 - - ds2.stateContext.lastHeaders.size shouldEqual 1 - - java.util.Arrays.equals(ds2.rootDigest, ds.rootDigest) shouldBe false - - val ds3 = ds2.rollbackTo(ds.version).get - ds3.rootDigest shouldBe ds.rootDigest - - ds3.stateContext.lastHeaders.size shouldEqual 0 - - ds3.applyModifier(block, None)(_ => ()).get.rootDigest shouldBe ds2.rootDigest - } - } - - property("validateTransactions() - dataInputs") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - val ds = createDigestState(us.version, us.rootDigest) - - // generate 2 independent transactions spending state boxes only - val headTx = validTransactionsFromBoxes(1, bh.boxes.take(10).values.toSeq, new RandomWrapper())._1.head - val nextTx = validTransactionsFromBoxes(1, bh.boxes.takeRight(10).values.toSeq, new RandomWrapper())._1.head - headTx.inputs.intersect(nextTx.inputs) shouldBe empty - - // trying to apply transactions with data inputs same as inputs of the next tx - val dataInputs = nextTx.inputs.filter(i => us.boxById(i.boxId).isDefined).map(i => DataInput(i.boxId)) - val inputs = headTx.outputs.map(b => Input(b.id, ProverResult.empty)) - val txWithDataInputs = ErgoTransaction(inputs, dataInputs, headTx.outputCandidates) - - val txs1 = IndexedSeq(headTx, nextTx, txWithDataInputs) - val (proofBytes1, digest1) = us.proofsForTransactions(txs1).get - val proof1 = ADProofs(defaultHeaderGen.sample.get.id, proofBytes1) - ds.validateTransactions(txs1, digest1, proof1, emptyStateContext) shouldBe 'success - - val txs2 = IndexedSeq(headTx, txWithDataInputs, nextTx) - val (proofBytes2, digest2) = us.proofsForTransactions(txs2).get - val proof2 = ADProofs(defaultHeaderGen.sample.get.id, proofBytes2) - ds.validateTransactions(txs2, digest2, proof2, emptyStateContext) shouldBe 'success - - val txs3 = IndexedSeq(txWithDataInputs, headTx, nextTx) - ds.validateTransactions(txs3, digest2, proof2, emptyStateContext) shouldBe 'failure - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateContextSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateContextSpec.scala deleted file mode 100644 index e5db6a6cbf..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateContextSpec.scala +++ /dev/null @@ -1,85 +0,0 @@ -package org.ergoplatform.nodeView.state - -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.settings.Parameters._ -import org.ergoplatform.utils.HistoryTestHelpers - -class ErgoStateContextSpec extends HistoryTestHelpers { - - property("Header votes") { - val fb = genChain(1).head - val header = fb.header - - def fbWithVotes(votes: Array[Byte], h: Int = 1): ErgoFullBlock = { - val newHeader = header.copy(votes = votes, version = 0: Byte, height = h) - fb.copy(header = newHeader) - } - - //double vote - val wrongVotes1 = Array(StorageFeeFactorIncrease, StorageFeeFactorIncrease, NoParameter) - emptyStateContext.appendFullBlock(fbWithVotes(wrongVotes1)) shouldBe 'failure - - //contradictory votes - val wrongVotes2 = Array(StorageFeeFactorIncrease, StorageFeeFactorDecrease, NoParameter) - emptyStateContext.appendFullBlock(fbWithVotes(wrongVotes2)) shouldBe 'failure - - //too many votes - only two ordinary changes allowed per epoch - val wrongVotes3 = Array(StorageFeeFactorIncrease, MaxBlockCostIncrease, MaxBlockSizeDecrease) - emptyStateContext.appendFullBlock(fbWithVotes(wrongVotes3)) shouldBe 'failure - - //a vote proposed on non-existing parameter - breaks rule #215 - //voting epoch length is 1024 blocks long - val wrongVotes4 = Array((-50).toByte, NoParameter, MaxBlockSizeDecrease) - emptyStateContext.appendFullBlock(fbWithVotes(wrongVotes4, 1024)) shouldBe 'failure - - //correct votes - val correctVotes = Array(StorageFeeFactorIncrease, MaxBlockSizeDecrease, NoParameter) - emptyStateContext.appendFullBlock(fbWithVotes(correctVotes)) shouldBe 'success - - - //a vote for non-existing parameter in the middle of epoch - does not break rule #215 - //voting epoch length is 1024 blocks long - val correctVotes2 = Array((-50).toByte, NoParameter, MaxBlockSizeDecrease) - emptyStateContext.appendFullBlock(fbWithVotes(correctVotes2, 2)) shouldBe 'success - - } - - property("Extension validation") { - val chain = genChain(2) - val sc = emptyStateContext.appendFullBlock(chain.head).get - val fb = chain.last - val extension = fb.extension - val oldFields = extension.fields - - def fbWithFields(newFields: Seq[(Array[Byte], Array[Byte])]): ErgoFullBlock = { - val newExtension = extension.copy(fields = newFields) - fb.copy(extension = newExtension) - } - - // checks, specific for extension - // validation of field keys size - val imvKey = extensionKvGen(Extension.FieldKeySize - 1, Extension.FieldValueMaxSize).sample.get - sc.appendFullBlock(fbWithFields(imvKey +: oldFields)) shouldBe 'failure - - // validation of field value sizes - val imvValue = extensionKvGen(Extension.FieldKeySize, Extension.FieldValueMaxSize + 1).sample.get - sc.appendFullBlock(fbWithFields(imvValue +: oldFields)) shouldBe 'failure - - // validation of incorrect interlinks - val invalidInterlinks = nipopowAlgos.interlinksToExtension( - NipopowAlgos.unpackInterlinks(fb.extension.fields).get ++ Seq(fb.header.id) - ).fields - sc.appendFullBlock(fbWithFields(invalidInterlinks ++ oldFields)) shouldBe 'failure - - // validation of key duplicates in fields - val validMKV = extensionKvGen(Extension.FieldKeySize, Extension.FieldValueMaxSize).sample.get - sc.appendFullBlock(fbWithFields(Seq(validMKV, validMKV) ++ oldFields)) shouldBe 'failure - - // valid application of correct extension - sc.appendFullBlock(fbWithFields(validMKV +: oldFields)) shouldBe 'success - - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala deleted file mode 100644 index 059b4e0d1c..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala +++ /dev/null @@ -1,190 +0,0 @@ -package org.ergoplatform.nodeView.state - -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.settings.{Args, ErgoSettings} -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.wallet.boxes.ErgoBoxSerializer -import org.scalacheck.Gen -import scorex.core.bytesToVersion -import scorex.core.validation.ValidationResult.Valid -import scorex.db.ByteArrayWrapper - -import scala.collection.mutable -import scala.util.{Failure, Try} - -class ErgoStateSpecification extends ErgoPropertyTest { - - property("applyModifier() - double spending") { - forAll(boxesHolderGen, Gen.choose(1: Byte, 2: Byte)) { case (bh, version) => - val us = createUtxoState(bh, parameters) - val ds = createDigestState(bytesToVersion(Array.fill(32)(100: Byte)), us.rootDigest) - - val validBlock = validFullBlock(None, us, bh) - val dsTxs = validBlock.transactions ++ validBlock.transactions - ErgoState.stateChanges(dsTxs) shouldBe 'failure - - val dsRoot = BlockTransactions.transactionsRoot(dsTxs, version) - val dsHeader = validBlock.header.copy(transactionsRoot = dsRoot) - val bt = BlockTransactions(dsHeader.id, version, dsTxs) - val doubleSpendBlock = ErgoFullBlock(dsHeader, bt, validBlock.extension, validBlock.adProofs) - - us.applyModifier(doubleSpendBlock, None)(_ => ()) shouldBe 'failure - us.applyModifier(validBlock, None)(_ => ()) shouldBe 'success - - ds.applyModifier(doubleSpendBlock, None)(_ => ()) shouldBe 'failure - ds.applyModifier(validBlock, None)(_ => ()) shouldBe 'success - } - } - - property("stateContext should be the same for Utxo and Digest states") { - def requireEqualStateContexts(s1: ErgoStateContext, s2: ErgoStateContext, lastHeaders: Seq[Header]): Unit = { - s1.currentHeight shouldBe lastHeaders.headOption.map(_.height).getOrElse(0) - s1.currentHeight shouldBe s2.currentHeight - s1.previousStateDigest shouldEqual s2.previousStateDigest - s1.lastHeaders shouldEqual s2.lastHeaders - s1.lastHeaders shouldEqual lastHeaders - s1.currentParameters shouldEqual s2.currentParameters - s1.votingData shouldEqual s2.votingData - s1.genesisStateDigest shouldBe s2.genesisStateDigest - } - - var (us, bh) = createUtxoState(settings) - var ds = createDigestState(us.version, us.rootDigest) - var lastBlocks: Seq[ErgoFullBlock] = Seq() - forAll { seed: Int => - val blBh = validFullBlockWithBoxHolder(lastBlocks.headOption, us, bh, new RandomWrapper(Some(seed))) - val block = blBh._1 - bh = blBh._2 - ds = ds.applyModifier(block, None)(_ => ()).get - us = us.applyModifier(block, None)(_ => ()).get - lastBlocks = block +: lastBlocks - requireEqualStateContexts(us.stateContext, ds.stateContext, lastBlocks.map(_.header)) - } - } - - property("generateGenesisUtxoState & generateGenesisDigestState are compliant") { - val settings = ErgoSettings.read(Args.empty) - val dir = createTempDir - val rootHash = createUtxoState(settings)._1.rootDigest - val expectedRootHash = ErgoState.generateGenesisDigestState(dir, settings).rootDigest - rootHash shouldBe expectedRootHash - } - - property("ErgoState.boxChanges() should generate operations in the same order") { - var (us, bh) = createUtxoState(settings) - var parentOpt: Option[ErgoFullBlock] = None - - forAll { seed: Int => - val blBh = validFullBlockWithBoxHolder(parentOpt, us, bh, new RandomWrapper(Some(seed))) - val block = blBh._1 - parentOpt = Some(block) - bh = blBh._2 - us = us.applyModifier(block, None)(_ => ()).get - - val changes1 = ErgoState.boxChanges(block.transactions).get - val changes2 = ErgoState.boxChanges(block.transactions).get - changes1._1 shouldBe changes2._1 - changes1._2 shouldBe changes2._2 - } - } - - property("ErgoState.boxChanges() double spend attempt") { - val (_, bh) = createUtxoState(settings) - val emissionBox = genesisBoxes.head - - forAll { seed: Int => - val txs = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(seed)))._1 - whenever(txs.lengthCompare(2) > 0) { - // valid transaction should spend the only existing genesis box - ErgoState.boxChanges(txs).get._1.length shouldBe 1 - ErgoState.boxChanges(txs).get._1.head.key shouldBe emissionBox.id - - // second transaction input should be an input created by the first transaction - val inputToDoubleSpend = txs(1).inputs.head - txs.head.outputs.find(b => java.util.Arrays.equals(b.id, inputToDoubleSpend.boxId)) should not be None - val doubleSpendTx = txs.last.copy(inputs = inputToDoubleSpend +: txs.last.inputs.tail) - val invalidTxs = txs.dropRight(1) :+ doubleSpendTx - invalidTxs.length shouldBe txs.length - invalidTxs.count(_.inputs.contains(inputToDoubleSpend)) shouldBe 2 - - ErgoState.boxChanges(invalidTxs).get._1.length shouldBe 2 - } - } - } - - property("ErgoState.stateChanges()") { - val bh = createUtxoState(settings)._2 - val emissionBox = genesisBoxes.head - - forAll { seed: Int => - val txs = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(seed)))._1 - whenever(txs.lengthCompare(1) > 0) { - val changes = ErgoState.stateChanges(txs).get - val removals = changes.toRemove - // should remove the only genesis box from the state - removals.length shouldBe 1 - removals.head.key shouldEqual emissionBox.id - // number of inputs should be more than 1 - we create boxes and spend them in the same block - txs.flatMap(_.inputs).length should be > 1 - - val insertions = changes.toAppend - // sum of coins in outputs should equal to genesis value - insertions.map(_.value).map(ErgoBoxSerializer.parseBytes).map(_.value).sum shouldBe emissionBox.value - - // if output was spend and then created - it is in both toInsert and toRemove - val changesRev = ErgoState.stateChanges(txs.reverse).get - val removalsRev = changesRev.toRemove - val insertionsRev = changesRev.toAppend - removalsRev.length should be > removals.length - insertionsRev.length should be > insertions.length - } - } - } - - property("ErgoState.execTransactions()") { - val bh = BoxHolder(genesisBoxes) - def generateTxs = - (1 to 15).foldLeft(mutable.WrappedArray.newBuilder[ErgoTransaction]) { case (txAcc, _) => - val (transactions, _) = validTransactionsFromBoxes(10000, bh.boxes.values.toSeq, new RandomWrapper()) - val allBoxIds = bh.boxes.keys.toSet - val txsFromBoxesOnly = transactions.filter { tx => - tx.inputs.map(i => ByteArrayWrapper(i.boxId)).forall(allBoxIds.contains) && - tx.dataInputs.map(i => ByteArrayWrapper(i.boxId)).forall(allBoxIds.contains) - } - txAcc ++= txsFromBoxesOnly - }.result() - - val txs = generateTxs - val boxes = bh.boxes - val stateContext = emptyStateContext - val expectedCost = 185160 - - // successful validation - ErgoState.execTransactions(txs, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))) shouldBe Valid(expectedCost) - - // cost limit exception expected when crossing MaxBlockCost - val tooManyTxs = (1 to 10).flatMap(_ => generateTxs) - assert( - ErgoState.execTransactions(tooManyTxs, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))).errors.head.message.contains( - "Accumulated cost of block transactions should not exceed " - ) - ) - - // missing box in state - ErgoState.execTransactions(txs, stateContext)(_ => Failure(new RuntimeException)).errors.head.message shouldBe - "Every input of the transaction should be in UTXO. null" - - // tx validation should kick in and detect block height violation - val invalidTx = invalidErgoTransactionGen.sample.get - assert( - ErgoState.execTransactions(txs :+ invalidTx, stateContext)(id => Try(boxes.getOrElse(ByteArrayWrapper(id), invalidTx.outputs.head))) - .errors.head.message.startsWith("Transaction outputs should have creationHeight not exceeding block height.") - ) - - // no transactions are valid - assert(ErgoState.execTransactions(Seq.empty, stateContext)(id => Try(boxes(ByteArrayWrapper(id)))).isValid) - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsDbSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsDbSpecification.scala deleted file mode 100644 index f273749ca7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsDbSpecification.scala +++ /dev/null @@ -1,51 +0,0 @@ -package org.ergoplatform.nodeView.state - -import org.ergoplatform.utils.ErgoPropertyTest -import org.scalacheck.Gen -import scorex.crypto.hash.Digest32 -import scorex.util.{ModifierId, bytesToId, idToBytes} - -import scala.util.Random - -class SnapshotsDbSpecification extends ErgoPropertyTest { - - def seededDatabase(manifestIds: Seq[ModifierId]): (SnapshotsInfo, SnapshotsDb) = { - val m = manifestIds.map { mid => - Random.nextInt(1000000) -> (Digest32 @@ idToBytes(mid)) - }.toMap - val si = new SnapshotsInfo(m) - val dir = createTempDir.getAbsolutePath - val db = SnapshotsDb.create(dir) - db.writeSnapshotsInfo(si) - si -> db - } - - property("snapshotsInfo round-trip") { - forAll(Gen.nonEmptyListOf(modifierIdGen)) { manifestIds => - val (si, db) = seededDatabase(manifestIds) - val read = db.readSnapshotsInfo.availableManifests.mapValues(bs => bytesToId(bs)) - val siTocompare = si.availableManifests.mapValues(bs => bytesToId(bs)) - read shouldBe siTocompare - } - } - - property("pruneSnapshots choosing snapshots correctly") { - forAll(Gen.nonEmptyListOf(modifierIdGen)) { manifestIds => - val (si, db) = seededDatabase(manifestIds) - - val toStore = Random.nextInt(manifestIds.size + 3) - - db.pruneSnapshots(toStore) - - val after = db.readSnapshotsInfo - - if (toStore >= manifestIds.size) { - after.availableManifests.size == manifestIds.size - } else { - val storedKeys = si.availableManifests.keySet.toSeq.sorted.takeRight(toStore) - val stored = si.availableManifests.filterKeys(h => storedKeys.contains(h)) - after.availableManifests.mapValues(bytesToId) shouldBe stored.mapValues(bytesToId) - } - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsInfoSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsInfoSpecification.scala deleted file mode 100644 index 4f3b0ffe79..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/SnapshotsInfoSpecification.scala +++ /dev/null @@ -1,25 +0,0 @@ -package org.ergoplatform.nodeView.state - -import org.ergoplatform.utils.ErgoPropertyTest - -class SnapshotsInfoSpecification extends ErgoPropertyTest { - - property("makeEmpty / nonEmpty / withNewManifest") { - val empty = SnapshotsInfo.empty - empty.nonEmpty shouldBe false - - val h = 10 - val d = digest32Gen.sample.get - val nonEmpty = empty.withNewManifest(h, d) - nonEmpty.nonEmpty shouldBe true - nonEmpty.availableManifests(h).sameElements(d) shouldBe true - - val h2 = 20 - val d2 = digest32Gen.sample.get - val ne2 = nonEmpty.withNewManifest(h2, d2) - nonEmpty.availableManifests.size shouldBe 1 - ne2.availableManifests(h).sameElements(d) shouldBe true - ne2.availableManifests(h2).sameElements(d2) shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala deleted file mode 100644 index e3dc146a8c..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala +++ /dev/null @@ -1,528 +0,0 @@ -package org.ergoplatform.nodeView.state - -import java.util.concurrent.Executors -import org.ergoplatform.ErgoBox.{BoxId, R4} -import org.ergoplatform._ -import org.ergoplatform.mining._ -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions} -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} -import org.ergoplatform.utils.generators.ErgoTransactionGenerators -import scorex.core._ -import scorex.core.transaction.TooHighCostError -import scorex.crypto.authds.ADKey -import scorex.db.ByteArrayWrapper -import scorex.util.{ModifierId, bytesToId} -import scorex.util.encode.Base16 -import sigmastate.Values.ByteArrayConstant -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.interpreter.ProverResult -import sigmastate.helpers.TestingHelpers._ - -import scala.concurrent.duration.Duration -import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor, Future} -import scala.util.Try - - -class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenerators { - - private val emptyModifierId: ModifierId = bytesToId(Array.fill(32)(0.toByte)) - - property("Founders box workflow") { - var (us, bh) = createUtxoState(settings) - var foundersBox = genesisBoxes.last - var lastBlock = validFullBlock(parentOpt = None, us, bh) - us = us.applyModifier(lastBlock, None)(_ => ()).get - - // spent founders box, leaving the same proposition - (0 until 10) foreach { _ => - val height = us.stateContext.currentHeight - val inputs = IndexedSeq(Input(foundersBox.id, emptyProverResult)) - val remaining = emission.remainingFoundationRewardAtHeight(height) - val newFoundersBox = testBox(remaining, foundersBox.ergoTree, height, Seq(), Map(R4 -> foundersBox.additionalRegisters(R4))) - val rewardBox = testBox(foundersBox.value - remaining, defaultProver.hdKeys.last.publicImage, height) - val newBoxes = IndexedSeq(newFoundersBox, rewardBox) - val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), newBoxes) - val tx: ErgoTransaction = ErgoTransaction(defaultProver.sign(unsignedTx, IndexedSeq(foundersBox), emptyDataBoxes, us.stateContext).get) - val txCostLimit = initSettings.nodeSettings.maxTransactionCost - us.validateWithCost(tx, us.stateContext.simplifiedUpcoming(), txCostLimit, None).get should be <= 100000 - val block1 = validFullBlock(Some(lastBlock), us, Seq(ErgoTransaction(tx))) - us = us.applyModifier(block1, None)(_ => ()).get - foundersBox = tx.outputs.head - lastBlock = block1 - } - } - - property("Founders should be able to spend genesis founders box") { - var (us, bh) = createUtxoState(settings) - val foundersBox = genesisBoxes.last - var height: Int = ErgoHistory.GenesisHeight - - val settingsPks = settings.chainSettings.foundersPubkeys - .map(str => groupElemFromBytes(Base16.decode(str).get)) - .map(pk => ProveDlog(pk)) - settingsPks.count(defaultProver.hdPubKeys.map(_.key).contains) shouldBe 2 - - forAll(defaultHeaderGen) { header => - val rewardPk = new DLogProverInput(BigInt(header.height).bigInteger).publicImage - - val t = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(height))) - val txs = t._1 - bh = t._2 - val (adProofBytes, adDigest) = us.proofsForTransactions(txs).get - val realHeader = header.copy(stateRoot = adDigest, - ADProofsRoot = ADProofs.proofDigest(adProofBytes), - height = height, - parentId = us.stateContext.lastHeaderOpt.map(_.id).getOrElse(Header.GenesisParentId)) - val adProofs = ADProofs(realHeader.id, adProofBytes) - val bt = BlockTransactions(realHeader.id, Header.InitialVersion, txs) - val fb = ErgoFullBlock(realHeader, bt, genExtension(realHeader, us.stateContext), Some(adProofs)) - us = us.applyModifier(fb, None)(_ => ()).get - val remaining = emission.remainingFoundationRewardAtHeight(height) - - // check validity of transaction, spending founders box - val inputs = IndexedSeq(Input(foundersBox.id, emptyProverResult)) - val newBoxes = IndexedSeq( - testBox(remaining, foundersBox.ergoTree, height, Seq(), foundersBox.additionalRegisters), - testBox(foundersBox.value - remaining, rewardPk, height, Seq()) - ) - val unsignedTx = new UnsignedErgoTransaction(inputs, IndexedSeq(), newBoxes) - val tx = ErgoTransaction(defaultProver.sign(unsignedTx, IndexedSeq(foundersBox), emptyDataBoxes, us.stateContext).get) - val validationContext = us.stateContext.simplifiedUpcoming() - val validationRes1 = us.validateWithCost(tx, validationContext, 100000, None) - validationRes1 shouldBe 'success - val txCost = validationRes1.get - - val validationRes2 = us.validateWithCost(tx, validationContext, txCost - 1, None) - validationRes2 shouldBe 'failure - validationRes2.toEither.left.get.isInstanceOf[TooHighCostError] shouldBe true - - us.validateWithCost(tx, validationContext, txCost + 1, None) shouldBe 'success - - us.validateWithCost(tx, validationContext, txCost, None) shouldBe 'success - - height = height + 1 - } - } - - property("Correct genesis state") { - val (us, bh) = createUtxoState(settings) - val boxes = bh.boxes.values.toList - boxes.size shouldBe 3 - - // check tests consistency - genesisBoxes.length shouldBe bh.boxes.size - genesisBoxes.foreach { b => - us.boxById(b.id).isDefined shouldBe true - bh.boxes.contains(ByteArrayWrapper(b.id)) shouldBe true - } - - // check total supply - boxes.map(_.value).sum shouldBe coinsTotal - - // boxes should contain all no-premine proofs in registers - val additionalRegisters = boxes.flatMap(_.additionalRegisters.values) - initSettings.chainSettings.noPremineProof.foreach { pStr => - val pBytes = ByteArrayConstant(pStr.getBytes("UTF-8")) - additionalRegisters should contain(pBytes) - } - - } - - property("extractEmissionBox() should extract correct box") { - var (us, bh) = createUtxoState(settings) - us.emissionBoxOpt should not be None - var lastBlockOpt: Option[ErgoFullBlock] = None - forAll { seed: Int => - val blBh = validFullBlockWithBoxHolder(lastBlockOpt, us, bh, new RandomWrapper(Some(seed))) - val block = blBh._1 - us.extractEmissionBox(block) should not be None - lastBlockOpt = Some(block) - bh = blBh._2 - us = us.applyModifier(block, None)(_ => ()).get - } - } - - property("fromBoxHolder") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - bh.take(1000)._1.foreach { box => - us.boxById(box.id) shouldBe Some(box) - } - } - } - - property("proofsForTransactions") { - var (us: UtxoState, bh) = createUtxoState(settings) - var height: Int = ErgoHistory.GenesisHeight - forAll(defaultHeaderGen) { header => - val t = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(height))) - val txs = t._1 - bh = t._2 - val (adProofBytes, adDigest) = us.proofsForTransactions(txs).get - val realHeader = header.copy(stateRoot = adDigest, - ADProofsRoot = ADProofs.proofDigest(adProofBytes), - height = height, - parentId = us.stateContext.lastHeaderOpt.map(_.id).getOrElse(Header.GenesisParentId)) - val adProofs = ADProofs(realHeader.id, adProofBytes) - val bt = BlockTransactions(realHeader.id, 1: Byte, txs) - val fb = ErgoFullBlock(realHeader, bt, genExtension(realHeader, us.stateContext), Some(adProofs)) - us = us.applyModifier(fb, None)(_ => ()).get - height = height + 1 - } - } - - property("concurrent applyModifier() and proofsForTransactions()") { - implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(4)) - - var bh = BoxHolder(Seq(genesisEmissionBox)) - var us = createUtxoState(bh, parameters) - - var height: Int = ErgoHistory.GenesisHeight - // generate chain of correct full blocks - val chain = (0 until 10) map { _ => - val header = defaultHeaderGen.sample.value - val t = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(height))) - val txs = t._1 - bh = t._2 - val (adProofBytes, adDigest) = us.proofsForTransactions(txs).get - val realHeader = header.copy(stateRoot = adDigest, - ADProofsRoot = ADProofs.proofDigest(adProofBytes), - height = height, - parentId = us.stateContext.lastHeaderOpt.map(_.id).getOrElse(Header.GenesisParentId)) - val adProofs = ADProofs(realHeader.id, adProofBytes) - height = height + 1 - val bt = BlockTransactions(realHeader.id, Header.InitialVersion, txs) - val fb = ErgoFullBlock(realHeader, bt, genExtension(realHeader, us.stateContext), Some(adProofs)) - us = us.applyModifier(fb, None)(_ => ()).get - fb - } - // create new genesis state - var us2 = createUtxoState(BoxHolder(Seq(genesisEmissionBox)), parameters) - val stateReader = us2.getReader.asInstanceOf[UtxoState] - // parallel thread that generates proofs - val f = Future { - (0 until 1000) foreach { _ => - Try { - val boxes = stateReader.randomBox().toSeq - val txs = validTransactionsFromBoxes(400, boxes, new RandomWrapper)._1 - stateReader.proofsForTransactions(txs).get - } - } - } - // apply chain of headers full block to state - chain.foreach { fb => - us2 = us2.applyModifier(fb, None)(_ => ()).get - } - Await.result(f, Duration.Inf) - } - - property("proofsForTransactions() to be deterministic") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - val txs = validTransactionsFromBoxHolder(bh)._1 - - val (proof1, digest1) = us.proofsForTransactions(txs).get - val (proof2, digest2) = us.proofsForTransactions(txs).get - - ADProofs.proofDigest(proof1) shouldBe ADProofs.proofDigest(proof2) - digest1 shouldBe digest2 - } - } - - property("applyTransactions() - simple case for transaction with dataInputs") { - forAll(boxesHolderGen) { bh => - val txsIn = validTransactionsFromBoxHolder(bh)._1 - val headTx = txsIn.head - val us = createUtxoState(bh, parameters) - val existingBoxes: IndexedSeq[BoxId] = bh.boxes.takeRight(3).map(_._2.id).toIndexedSeq - - // trying to apply transactions with missing data inputs - val missedId: BoxId = ADKey @@ scorex.util.Random.randomBytes() - us.boxById(missedId) shouldBe None - val missingDataInputs = (missedId +: existingBoxes).map(DataInput).toIndexedSeq - val txWithMissedDataInputs = ErgoTransaction(headTx.inputs, missingDataInputs, headTx.outputCandidates) - val incorrectTransactions = IndexedSeq(txWithMissedDataInputs) - // proof for transaction works correctly, providing proof-of-non-existence for missed input - val digest2 = us.proofsForTransactions(incorrectTransactions).get._2 - us.applyTransactions(incorrectTransactions, emptyModifierId, digest2, emptyStateContext) shouldBe 'failure - - // trying to apply transactions with correct data inputs - val existingDataInputs = existingBoxes.map(DataInput).toIndexedSeq - existingDataInputs.foreach(b => us.boxById(b.boxId) should not be None) - val txWithDataInputs = ErgoTransaction(headTx.inputs, existingDataInputs, headTx.outputCandidates) - val correctTransactions = IndexedSeq(txWithDataInputs) - val digest = us.proofsForTransactions(correctTransactions).get._2 - us.applyTransactions(correctTransactions, emptyModifierId, digest, emptyStateContext).get - } - } - - property("applyTransactions() - dataInputs intersect with inputs") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - - // generate 2 independent transactions, that only spend state boxes - val headTx = validTransactionsFromBoxes(1, bh.boxes.take(10).values.toSeq, new RandomWrapper())._1.head - val nextTx = validTransactionsFromBoxes(1, bh.boxes.takeRight(10).values.toSeq, new RandomWrapper())._1.head - headTx.inputs.intersect(nextTx.inputs) shouldBe empty - - // trying to apply transactions with data inputs same as inputs of the next tx - val dataInputs = nextTx.inputs.filter(i => us.boxById(i.boxId).isDefined).map(i => DataInput(i.boxId)) - val txWithDataInputs = ErgoTransaction(headTx.inputs, dataInputs, headTx.outputCandidates) - - val txs1 = IndexedSeq(headTx, nextTx) - val txs2 = IndexedSeq(txWithDataInputs, nextTx) - val sc1 = ErgoState.stateChanges(txs1).get - val sc2 = ErgoState.stateChanges(IndexedSeq(txWithDataInputs, nextTx)).get - // check that the only difference between txs1 and txs2 are dataInputs and Lookup tree operations - txs1.flatMap(_.inputs) shouldBe txs2.flatMap(_.inputs) - txs1.flatMap(_.outputCandidates) shouldBe txs2.flatMap(_.outputCandidates) - sc1.toAppend.size shouldBe sc2.toAppend.size - sc1.toRemove shouldBe sc2.toRemove - - us.proofsForTransactions(txs1) shouldBe 'success - us.proofsForTransactions(txs2) shouldBe 'success - - val inputs = headTx.outputs.map(b => Input(b.id, ProverResult.empty)) - val txWithDataInputs2 = ErgoTransaction(inputs, dataInputs, headTx.outputCandidates) - - val version = us.version - - val txs3 = IndexedSeq(headTx, nextTx, txWithDataInputs2) - val (_, digest3) = us.proofsForTransactions(txs3).get - us.applyTransactions(txs3, emptyModifierId, digest3, emptyStateContext) shouldBe 'success - us.rollbackTo(version) - - val txs4 = IndexedSeq(headTx, txWithDataInputs2, nextTx) - val (_, digest4) = us.proofsForTransactions(txs4).get - us.applyTransactions(txs4, emptyModifierId, digest4, emptyStateContext) shouldBe 'success - us.rollbackTo(version) - - val txs5 = IndexedSeq(txWithDataInputs2, headTx, nextTx) - us.proofsForTransactions(txs5) shouldBe 'failure - us.applyTransactions(txs5, emptyModifierId, digest4, emptyStateContext) shouldBe 'failure - us.rollbackTo(version) - - // trying to apply transactions with data inputs same as outputs of the previous tx - val dataInputsNext = headTx.outputs.take(1).map(i => DataInput(i.id)) - dataInputsNext should not be empty - val nextTxWithDataInputs = ErgoTransaction(nextTx.inputs, dataInputsNext, nextTx.outputCandidates) - val txsNext = IndexedSeq(headTx, nextTxWithDataInputs) - // proof of non-existence - val d2 = us.proofsForTransactions(txsNext).get._2 - us.applyTransactions(txsNext, emptyModifierId, d2, emptyStateContext) shouldBe 'success - } - } - - property("applyTransactions() - simple case") { - forAll(boxesHolderGen) { bh => - val txs = validTransactionsFromBoxHolder(bh)._1 - - val created = txs.flatMap(_.outputs.map(_.id)).map(ByteArrayWrapper.apply) - val boxIds = txs.flatMap(_.inputs.map(_.boxId)).map(ByteArrayWrapper.apply) - boxIds.distinct.size shouldBe boxIds.size - val toRemove = boxIds.filterNot(id => created.contains(id)) - toRemove.foreach(id => bh.get(id) should not be None) - - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - val digest = us.proofsForTransactions(txs).get._2 - val wBlock = invalidErgoFullBlockGen.sample.get - val block = wBlock.copy(header = wBlock.header.copy(height = 1)) - val newSC = us.stateContext.appendFullBlock(block).get - us.applyTransactions(txs, emptyModifierId, digest, newSC).get - } - } - - property("applyTransactions() - a transaction is spending an output created by a previous transaction") { - forAll(boxesHolderGen) { bh => - val txsFromHolder = validTransactionsFromBoxHolder(bh)._1 - - val boxToSpend = txsFromHolder.last.outputs.head - - val spendingTxInput = Input(boxToSpend.id, emptyProverResult) - val spendingTx = ErgoTransaction( - IndexedSeq(spendingTxInput), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.TrueLeaf, creationHeight = startHeight)) - ) - val txs = txsFromHolder :+ spendingTx - - val us = createUtxoState(bh, parameters) - val digest = us.proofsForTransactions(txs).get._2 - - val header = invalidHeaderGen.sample.get.copy(stateRoot = digest, height = 1) - val bt = new BlockTransactions(header.id, 1: Byte, txs) - val fb = new ErgoFullBlock(header, bt, genExtension(header, us.stateContext), None) - val newSC = us.stateContext.appendFullBlock(fb).get - us.applyTransactions(txs, emptyModifierId, digest, newSC).get - } - } - - property("applyTransactions() - no double-spend of an output created in a block is possible") { - forAll(boxesHolderGen) { bh => - val txsFromHolder = validTransactionsFromBoxHolder(bh)._1 - - val boxToSpend = txsFromHolder.last.outputs.head - - val spendingTxInput = Input(boxToSpend.id, emptyProverResult) - val spendingTx = ErgoTransaction( - IndexedSeq(spendingTxInput), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.TrueLeaf, creationHeight = startHeight)) - ) - - val spending2Tx = ErgoTransaction( - IndexedSeq(Input(spendingTx.outputs.head.id, emptyProverResult)), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.TrueLeaf, creationHeight = startHeight)) - ) - - val spending3Tx = ErgoTransaction( - IndexedSeq(Input(spending2Tx.outputs.head.id, emptyProverResult)), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.TrueLeaf, creationHeight = startHeight)) - ) - - val spending4Tx = ErgoTransaction( - IndexedSeq(Input(spending2Tx.outputs.head.id, emptyProverResult)), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.FalseLeaf, creationHeight = startHeight)) - ) - - val txs = txsFromHolder ++ Seq(spendingTx, spending2Tx, spending3Tx, spending4Tx) - - val us = createUtxoState(bh, parameters) - - // Fails on generating state root digest for the block - us.proofsForTransactions(txs).isSuccess shouldBe false - } - } - - property("proofsForTransactions() fails if a transaction is spending an output created by a follow-up transaction") { - forAll(boxesHolderGen) { bh => - val txsFromHolder = validTransactionsFromBoxHolder(bh)._1 - - val boxToSpend = txsFromHolder.last.outputs.head - - val spendingTxInput = Input(boxToSpend.id, emptyProverResult) - val spendingTx = ErgoTransaction( - IndexedSeq(spendingTxInput), - IndexedSeq(), - IndexedSeq(new ErgoBoxCandidate(boxToSpend.value, Constants.TrueLeaf, creationHeight = startHeight))) - - val txs = spendingTx +: txsFromHolder - - val us = createUtxoState(bh, parameters) - us.proofsForTransactions(txs).isSuccess shouldBe false - } - } - - property("applyModifier() - valid full block") { - forAll(boxesHolderGen) { bh => - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - - val block = validFullBlock(parentOpt = None, us, bh) - us.applyModifier(block, None)(_ => ()).get - } - } - - property("applyModifier() - invalid block") { - forAll(invalidErgoFullBlockGen) { b => - val state = createUtxoState(settings)._1 - state.applyModifier(b, None)(_ => ()).isFailure shouldBe true - } - } - - property("applyModifier() - valid full block after invalid one") { - val (us, bh) = createUtxoState(settings) - val validBlock = validFullBlock(parentOpt = None, us, bh) - - //Different state - val (us2, bh2) = { - lazy val initialBoxes: Seq[ErgoBox] = (1 to 1).map(_ => ergoBoxGenNoProp.sample.get) - - val bh = BoxHolder(initialBoxes) - - createUtxoState(bh, parameters) -> bh - } - val invalidBlock = validFullBlock(parentOpt = None, us2, bh2) - - us.applyModifier(invalidBlock, None)(_ => ()).isSuccess shouldBe false - us.applyModifier(validBlock, None)(_ => ()).isSuccess shouldBe true - } - - - property("2 forks switching") { - val (us, bh) = createUtxoState(settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - val chain1block1 = validFullBlock(Some(genesis), wusAfterGenesis) - val wusChain1Block1 = wusAfterGenesis.applyModifier(chain1block1)(_ => ()).get - val chain1block2 = validFullBlock(Some(chain1block1), wusChain1Block1) - - val (us2, bh2) = createUtxoState(settings) - val wus2AfterGenesis = WrappedUtxoState(us2, bh2, settings, parameters).applyModifier(genesis)(_ => ()).get - val chain2block1 = validFullBlock(Some(genesis), wus2AfterGenesis) - val wusChain2Block1 = wus2AfterGenesis.applyModifier(chain2block1)(_ => ()).get - val chain2block2 = validFullBlock(Some(chain2block1), wusChain2Block1) - - var (state, _) = createUtxoState(settings) - state = state.applyModifier(genesis, None)(_ => ()).get - - state = state.applyModifier(chain1block1, None)(_ => ()).get - - state = state.rollbackTo(idToVersion(genesis.id)).get - state = state.applyModifier(chain2block1, None)(_ => ()).get - state = state.applyModifier(chain2block2, None)(_ => ()).get - - state = state.rollbackTo(idToVersion(genesis.id)).get - state = state.applyModifier(chain1block1, None)(_ => ()).get - state = state.applyModifier(chain1block2, None)(_ => ()).get - - } - - property("rollback n blocks and apply again") { - forAll(boxesHolderGen, smallPositiveInt) { (bh, depth) => - whenever(depth > 0 && depth <= 5) { - val us = createUtxoState(bh, parameters) - bh.sortedBoxes.foreach(box => us.boxById(box.id) should not be None) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = WrappedUtxoState(us, bh, settings, parameters).applyModifier(genesis)(_ => ()).get - wusAfterGenesis.rootDigest shouldEqual genesis.header.stateRoot - - val (finalState: WrappedUtxoState, chain: Seq[ErgoFullBlock]) = (0 until depth) - .foldLeft((wusAfterGenesis, Seq(genesis))) { (sb, _) => - val state = sb._1 - val block = validFullBlock(parentOpt = Some(sb._2.last), state) - (state.applyModifier(block)(_ => ()).get, sb._2 ++ Seq(block)) - } - val finalRoot = finalState.rootDigest - finalRoot shouldEqual chain.last.header.stateRoot - - val rollbackedState = finalState.rollbackTo(idToVersion(genesis.id)).get - rollbackedState.rootDigest shouldEqual genesis.header.stateRoot - - val finalState2: WrappedUtxoState = chain.tail.foldLeft(rollbackedState) { (state, block) => - state.applyModifier(block)(_ => ()).get - } - - finalState2.rootDigest shouldEqual finalRoot - } - } - } - - - - private def genExtension(header: Header, sc: ErgoStateContext): Extension = { - nipopowAlgos.interlinksToExtension(nipopowAlgos.updateInterlinks(sc.lastHeaderOpt, sc.lastExtensionOpt)).toExtension(header.id) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala deleted file mode 100644 index fe1933fad9..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala +++ /dev/null @@ -1,28 +0,0 @@ -package org.ergoplatform.nodeView.state.wrapped - -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier -import org.ergoplatform.ErgoLikeContext.Height -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.state.DigestState -import org.ergoplatform.settings.ErgoSettings -import scorex.core.VersionTag - -import scala.util.Try - -class WrappedDigestState(val digestState: DigestState, - val wrappedUtxoState: WrappedUtxoState, - val settings: ErgoSettings) - extends DigestState(digestState.version, digestState.rootDigest, digestState.store, settings) { - - override def applyModifier(mod: BlockSection, estimatedTip: Option[Height]) - (generate: LocallyGeneratedModifier => Unit): Try[WrappedDigestState] = { - wrapped(super.applyModifier(mod, estimatedTip)(_ => ()), wrappedUtxoState.applyModifier(mod, estimatedTip)(_ => ())) - } - - override def rollbackTo(version: VersionTag): Try[WrappedDigestState] = { - wrapped(super.rollbackTo(version), wrappedUtxoState.rollbackTo(version)) - } - - private def wrapped(digestT: Try[DigestState], utxoT: Try[WrappedUtxoState]): Try[WrappedDigestState] = - digestT.flatMap(digest => utxoT.map(utxo => new WrappedDigestState(digest, utxo, settings))) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala deleted file mode 100644 index d747a4b5be..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala +++ /dev/null @@ -1,85 +0,0 @@ -package org.ergoplatform.nodeView.state.wrapped - -import java.io.File - -import akka.actor.ActorRef -import org.ergoplatform.ErgoBox -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier -import org.ergoplatform.ErgoLikeContext.Height -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.settings.{ErgoSettings, Parameters} -import org.ergoplatform.settings.Algos.HF -import org.ergoplatform.wallet.boxes.ErgoBoxSerializer -import scorex.core.{TransactionsCarryingPersistentNodeViewModifier, VersionTag, idToVersion} -import scorex.crypto.authds.avltree.batch._ -import scorex.crypto.hash.Digest32 -import scorex.db.{ByteArrayWrapper, LDBVersionedStore} - -import scala.util.{Failure, Success, Try} - -class WrappedUtxoState(prover: PersistentBatchAVLProver[Digest32, HF], - override val version: VersionTag, - store: LDBVersionedStore, - val versionedBoxHolder: VersionedInMemoryBoxHolder, - settings: ErgoSettings) - extends UtxoState(prover, version, store, settings) { - - def size: Int = versionedBoxHolder.size - - def takeBoxes(count: Int): Seq[ErgoBox] = versionedBoxHolder.take(count)._1 - - override def rollbackTo(version: VersionTag): Try[WrappedUtxoState] = super.rollbackTo(version) match { - case Success(us) => - val updHolder = versionedBoxHolder.rollback(us.version) - Success(new WrappedUtxoState(us.persistentProver, version, us.store, updHolder, settings)) - case Failure(e) => Failure(e) - } - - override def applyModifier(mod: BlockSection, estimatedTip: Option[Height] = None) - (generate: LocallyGeneratedModifier => Unit): Try[WrappedUtxoState] = - super.applyModifier(mod, estimatedTip)(generate) match { - case Success(us) => - mod match { - case ct: TransactionsCarryingPersistentNodeViewModifier => - // You can not get block with transactions not being of ErgoTransaction type so no type checks here. - - val changes = ErgoState.stateChanges(ct.transactions).get - val updHolder = versionedBoxHolder.applyChanges( - us.version, - changes.toRemove.map(_.key).map(ByteArrayWrapper.apply), - changes.toAppend.map(_.value).map(ErgoBoxSerializer.parseBytes)) - Success(new WrappedUtxoState(us.persistentProver, idToVersion(mod.id), us.store, updHolder, settings)) - case _ => - val updHolder = versionedBoxHolder.applyChanges(us.version, Seq(), Seq()) - Success(new WrappedUtxoState(us.persistentProver, idToVersion(mod.id), us.store, updHolder, settings)) - } - case Failure(e) => Failure(e) - } -} - -object WrappedUtxoState { - - def apply(boxHolder: BoxHolder, - dir: File, - nodeViewHolderRef: Option[ActorRef], - parameters: Parameters, - settings: ErgoSettings): WrappedUtxoState = { - val emissionBox = ErgoState.genesisBoxes(settings.chainSettings).headOption - val us = UtxoState.fromBoxHolder(boxHolder, emissionBox, dir, settings, parameters) - WrappedUtxoState(us, boxHolder, settings, parameters) - } - - def apply(us: UtxoState, boxHolder: BoxHolder, settings: ErgoSettings, parameters: Parameters): WrappedUtxoState = { - val boxes = boxHolder.boxes - - val version = us.version - val vbh = new VersionedInMemoryBoxHolder( - boxes, - IndexedSeq(version), - Map(version -> (Seq() -> boxHolder.sortedBoxes.toSeq)) - ) - - new WrappedUtxoState(us.persistentProver, ErgoState.genesisStateVersion, us.store, vbh, settings) - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala deleted file mode 100644 index 83e9243ad9..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala +++ /dev/null @@ -1,553 +0,0 @@ -package org.ergoplatform.nodeView.viewholder - -import java.io.File -import org.ergoplatform.ErgoBoxCandidate -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.StateType.Utxo -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.settings.{Algos, Constants, ErgoSettings} -import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers, NodeViewTestConfig, NodeViewTestOps, TestCase} -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._ -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ -import org.ergoplatform.nodeView.ErgoNodeViewHolder -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.ChainProgress -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome.Accepted -import scorex.crypto.authds.{ADKey, SerializedAdProof} -import scorex.testkit.utils.NoShrink -import scorex.util.{ModifierId, bytesToId} - -class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers with NodeViewTestOps with NoShrink { - - private val t0 = TestCase("check chain is healthy") { fixture => - val (us, bh) = createUtxoState(settings) - val block = validFullBlock(None, us, bh) - - val history = generateHistory(true, StateType.Utxo, false, 2) - - // too big chain update delay - val notAcceptableDelay = System.currentTimeMillis() - (initSettings.nodeSettings.acceptableChainUpdateDelay.toMillis + 100) - val invalidProgress = ChainProgress(block, 2, 3, notAcceptableDelay) - ErgoNodeViewHolder.checkChainIsHealthy(invalidProgress, history, initSettings).isInstanceOf[ChainIsStuck] shouldBe true - - // acceptable chain update delay - val acceptableDelay = System.currentTimeMillis() - 5 - val validProgress = ChainProgress(block, 2, 3, acceptableDelay) - ErgoNodeViewHolder.checkChainIsHealthy(validProgress, history, initSettings) shouldBe ChainIsHealthy - } - - - private val t1 = TestCase("check genesis state") { fixture => - import fixture._ - getCurrentState.rootDigest shouldBe getGenesisStateDigest - } - - private val t2 = TestCase("check history after genesis") { fixture => - import fixture._ - getBestHeaderOpt shouldBe None - } - - private val t3 = TestCase("apply valid block header") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val block = validFullBlock(None, us, bh) - - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - - //sending header - nodeViewHolderRef ! LocallyGeneratedModifier(block.header) - expectMsgType[SyntacticallySuccessfulModifier] - - getHistoryHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) - getLastHeadersLength(10) shouldBe 1 - getBestHeaderOpt shouldBe Some(block.header) - } - - private val t3a = TestCase("do not apply block headers in invalid order") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val parentBlock = validFullBlock(None, us, bh) - val block = validFullBlock(Some(parentBlock), us, bh) - - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - - //sending child header without parent header - nodeViewHolderRef ! ModifiersFromRemote(List(block.header)) - expectNoMsg() - - // sende correct header sequence - nodeViewHolderRef ! ModifiersFromRemote(List(parentBlock.header)) - expectMsgType[SyntacticallySuccessfulModifier] - - nodeViewHolderRef ! ModifiersFromRemote(List(block.header)) - expectMsgType[SyntacticallySuccessfulModifier] - - getHistoryHeight shouldBe 2 - } - - private val t4 = TestCase("apply valid block as genesis") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.header) - expectMsgType[SyntacticallySuccessfulModifier] - - if (verifyTransactions) { - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.blockTransactions) - expectMsgType[SyntacticallySuccessfulModifier] - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.adProofs.value) - expectMsgType[SyntacticallySuccessfulModifier] - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.extension) - expectMsgType[SyntacticallySuccessfulModifier] - getBestFullBlockOpt shouldBe Some(genesis) - } - } - - private val t5 = TestCase("apply full blocks after genesis") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, fixture.settings, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - }.get - applyBlock(genesis) shouldBe 'success - - val block = validFullBlock(Some(genesis), wusAfterGenesis) - applyBlock(block) shouldBe 'success - if (verifyTransactions) { - getBestFullBlockOpt shouldBe Some(block) - } - - getBestHeaderOpt shouldBe Some(block.header) - getHistoryHeight shouldBe block.header.height - getLastHeadersLength(10) shouldBe 2 - } - - private val t6 = TestCase("add transaction to memory pool") { fixture => - import fixture._ - if (stateType == Utxo) { - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - applyBlock(genesis) shouldBe 'success - - val boxes = ErgoState.newBoxes(genesis.transactions).find(_.ergoTree == Constants.TrueLeaf) - boxes.nonEmpty shouldBe true - - val tx = UnconfirmedTransaction(validTransactionFromBoxes(boxes.toIndexedSeq), None) - subscribeEvents(classOf[FailedTransaction]) - nodeViewHolderRef ! LocallyGeneratedTransaction(tx) - expectMsgType[Accepted] - getPoolSize shouldBe 1 - } - } - - private val t7 = TestCase("apply statefully invalid full block") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, fixture.settings, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - }.get - // TODO looks like another bug is still present here, see https://github.com/ergoplatform/ergo/issues/309 - if (verifyTransactions) { - applyBlock(genesis) shouldBe 'success - - val block = validFullBlock(Some(genesis), wusAfterGenesis) - val wusAfterBlock = wusAfterGenesis.applyModifier(block)(mod => nodeViewHolderRef ! mod).get - - applyBlock(block) shouldBe 'success - getBestHeaderOpt shouldBe Some(block.header) - if (verifyTransactions) { - getRootHash shouldBe Algos.encode(wusAfterBlock.rootDigest) - } - getBestHeaderOpt shouldBe Some(block.header) - - val brokenBlock = generateInvalidFullBlock(Some(block), wusAfterBlock) - applyBlock(brokenBlock) shouldBe 'success - - val brokenBlock2 = generateInvalidFullBlock(Some(block), wusAfterBlock) - brokenBlock2.header should not be brokenBlock.header - applyBlock(brokenBlock2) shouldBe 'success - - getBestFullBlockOpt shouldBe Some(block) - getRootHash shouldBe Algos.encode(wusAfterBlock.rootDigest) - getBestHeaderOpt shouldBe Some(block.header) - } - } - - /** - * Generates statefuly invalid full block (contains invalid transactions). - */ - private def generateInvalidFullBlock(parentBlockOpt: Option[ErgoFullBlock], parentState: WrappedUtxoState) = { - val validInterlinks = nipopowAlgos.updateInterlinks(parentBlockOpt.map(_.header), parentBlockOpt.map(_.extension)) - val extensionIn = nipopowAlgos.interlinksToExtension(validInterlinks).toExtension(modifierIdGen.sample.get) - val brokenBlockIn = validFullBlock(parentBlockOpt, parentState) - val headTx = brokenBlockIn.blockTransactions.txs.head - val wrongBoxId: ADKey = ADKey !@@ Algos.hash("wrong input") - val newInput = headTx.inputs.head.copy(boxId = wrongBoxId) - val brokenTransactionsIn = brokenBlockIn.blockTransactions - .copy(txs = headTx.copy(inputs = newInput +: headTx.inputs.tail) +: brokenBlockIn.blockTransactions.txs.tail) - val brokenHeader = brokenBlockIn.header - .copy(transactionsRoot = brokenTransactionsIn.digest, extensionRoot = extensionIn.digest) - val brokenTransactions = brokenTransactionsIn.copy(headerId = brokenHeader.id) - val brokenProofs = brokenBlockIn.adProofs.value.copy(headerId = brokenHeader.id) - val extension = extensionIn.copy(headerId = brokenHeader.id) - ErgoFullBlock(brokenHeader, brokenTransactions, extension, Some(brokenProofs)) - } - - private val t8 = TestCase("switching for a better chain") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, fixture.settings, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - }.get - - applyBlock(genesis) shouldBe 'success - getRootHash shouldBe Algos.encode(wusAfterGenesis.rootDigest) - - val chain1block1 = validFullBlock(Some(genesis), wusAfterGenesis) - val expectedBestFullBlockOpt = if (verifyTransactions) Some(chain1block1) else None - applyBlock(chain1block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val chain2block1 = validFullBlock(Some(genesis), wusAfterGenesis) - applyBlock(chain2block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val wusChain2Block1 = wusAfterGenesis.applyModifier(chain2block1)(mod => nodeViewHolderRef ! mod).get - val chain2block2 = validFullBlock(Some(chain2block1), wusChain2Block1) - chain2block1.header.stateRoot shouldEqual wusChain2Block1.rootDigest - - applyBlock(chain2block2) shouldBe 'success - if (verifyTransactions) { - getBestFullBlockEncodedId shouldBe Some(chain2block2.header.encodedId) - } - - getBestHeaderOpt shouldBe Some(chain2block2.header) - getRootHash shouldBe Algos.encode(chain2block2.header.stateRoot) - } - - private val t9 = TestCase("UTXO state should generate adProofs and put them in history") { fixture => - import fixture._ - if (stateType == StateType.Utxo) { - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.header) - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.blockTransactions) - nodeViewHolderRef ! LocallyGeneratedModifier(genesis.extension) - - getBestFullBlockOpt shouldBe Some(genesis) - getModifierById(genesis.adProofs.value.id) shouldBe genesis.adProofs - } - } - - private val t10 = TestCase("NodeViewHolder start from inconsistent state") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, fixture.settings, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - }.get - applyBlock(genesis) shouldBe 'success - - val block1 = validFullBlock(Some(genesis), wusAfterGenesis) - applyBlock(block1) shouldBe 'success - getBestFullBlockOpt shouldBe Some(block1) - getRootHash shouldBe Algos.encode(block1.header.stateRoot) - - stopNodeViewHolder() - val stateDir = new File(s"${nodeViewDir.getAbsolutePath}/state") - this.deleteRecursive(stateDir) - startNodeViewHolder() - - getRootHash shouldBe Algos.encode(block1.header.stateRoot) - } - - private val t11 = TestCase("apply payload in incorrect order (excluding extension)") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val genesis = validFullBlock(parentOpt = None, us, bh) - val wusAfterGenesis = - WrappedUtxoState(us, bh, fixture.settings, parameters).applyModifier(genesis) { mod => - nodeViewHolderRef ! mod - }.get - - applyBlock(genesis) shouldBe 'success - getRootHash shouldBe Algos.encode(wusAfterGenesis.rootDigest) - - val chain2block1 = validFullBlock(Some(genesis), wusAfterGenesis) - val wusChain2Block1 = wusAfterGenesis.applyModifier(chain2block1)(mod => nodeViewHolderRef ! mod).get - val chain2block2 = validFullBlock(Some(chain2block1), wusChain2Block1) - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - nodeViewHolderRef ! LocallyGeneratedModifier(chain2block1.header) - expectMsgType[SyntacticallySuccessfulModifier] - - applyBlock(chain2block2, excludeExt = true) shouldBe 'success - getBestHeaderOpt shouldBe Some(chain2block2.header) - getBestFullBlockEncodedId shouldBe Some(genesis.header.encodedId) - - applyPayload(chain2block1, excludeExt = true) shouldBe 'success - getBestHeaderEncodedId shouldBe Some(chain2block2.header.encodedId) - } - - private val t12 = TestCase("Do not apply txs with wrong header id") { fixture => - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - val block = validFullBlock(None, us, bh) - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - - //sending header - nodeViewHolderRef ! LocallyGeneratedModifier(block.header) - expectMsgType[SyntacticallySuccessfulModifier] - val currentHeight = getHistoryHeight - currentHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) - - val randomId = modifierIdGen.sample.value - val recoverableTxs = block.blockTransactions.copy(headerId = randomId) - val invalidTxsWithWrongOutputs = { - val txs = block.blockTransactions.transactions - val tx = txs.head - val wrongOutputs = tx.outputCandidates.map(o => - new ErgoBoxCandidate(o.value + 10L, o.ergoTree, currentHeight, o.additionalTokens, o.additionalRegisters) - ) - val wrongTxs = tx.copy(outputCandidates = wrongOutputs) +: txs.tail - block.blockTransactions.copy(txs = wrongTxs) - } - val invalidTxsWithWrongInputs = { - val txs = block.blockTransactions.transactions - val tx = txs.head - val wrongInputs = tx.inputs.map { input => - input.copy(boxId = ADKey @@ input.boxId.reverse) - } - val wrongTxs = tx.copy(inputs = wrongInputs) +: txs.tail - block.blockTransactions.copy(txs = wrongTxs) - } - - nodeViewHolderRef ! LocallyGeneratedModifier(recoverableTxs) - expectMsgType[RecoverableFailedModification] - - nodeViewHolderRef ! LocallyGeneratedModifier(invalidTxsWithWrongOutputs) - expectMsgType[SyntacticallyFailedModification] - - nodeViewHolderRef ! LocallyGeneratedModifier(invalidTxsWithWrongInputs) - expectMsgType[SyntacticallyFailedModification] - - nodeViewHolderRef ! LocallyGeneratedModifier(block.blockTransactions) - expectMsgType[SyntacticallySuccessfulModifier] - } - - private val t13 = TestCase("Do not apply wrong adProofs") { fixture => - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - val block = validFullBlock(None, us, bh) - getBestHeaderOpt shouldBe None - - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - - //sending header - nodeViewHolderRef ! LocallyGeneratedModifier(block.header) - expectMsgType[SyntacticallySuccessfulModifier] - - val randomId = modifierIdGen.sample.value - val wrongProofsBytes = SerializedAdProof @@ block.adProofs.value.proofBytes.reverse - val wrongProofs1 = block.adProofs.map(_.copy(headerId = randomId)) - val wrongProofs2 = block.adProofs.map(_.copy(proofBytes = wrongProofsBytes)) - - nodeViewHolderRef ! LocallyGeneratedModifier(wrongProofs1.value) - expectMsgType[RecoverableFailedModification] - - nodeViewHolderRef ! LocallyGeneratedModifier(wrongProofs2.value) - expectMsgType[SyntacticallyFailedModification] - - nodeViewHolderRef ! LocallyGeneratedModifier(block.adProofs.value) - expectMsgType[SyntacticallySuccessfulModifier] - } - - private val t14 = TestCase("do not apply genesis block header if " + - "it's not equal to genesisId from config") { fixture => - import fixture._ - updateConfig(genesisIdConfig(modifierIdGen.sample)) - val (us, bh) = createUtxoState(fixture.settings) - val block = validFullBlock(None, us, bh) - - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - - //sending header - nodeViewHolderRef ! LocallyGeneratedModifier(block.header) - expectMsgType[SyntacticallyFailedModification] - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - } - - private val t15 = TestCase("apply genesis block header if it's equal to genesisId from config") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val block = validFullBlock(None, us, bh) - updateConfig(genesisIdConfig(Some(block.header.id))) - - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - - nodeViewHolderRef ! LocallyGeneratedModifier(block.header) - expectMsgType[SyntacticallySuccessfulModifier] - getHistoryHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) - } - - private val t16 = TestCase("apply forks that include genesis block") { fixture => - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - val wusGenesis = WrappedUtxoState(us, bh, fixture.settings, parameters) - - - val chain1block1 = validFullBlock(parentOpt = None, us, bh) - val expectedBestFullBlockOpt = if (verifyTransactions) Some(chain1block1) else None - applyBlock(chain1block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val chain2block1 = validFullBlock(parentOpt = None, us, bh) - applyBlock(chain2block1) shouldBe 'success - getBestFullBlockOpt shouldBe expectedBestFullBlockOpt - getBestHeaderOpt shouldBe Some(chain1block1.header) - - val wusChain2Block1 = wusGenesis.applyModifier(chain2block1)(mod => nodeViewHolderRef ! mod).get - val chain2block2 = validFullBlock(Some(chain2block1), wusChain2Block1) - chain2block1.header.stateRoot shouldEqual wusChain2Block1.rootDigest - - applyBlock(chain2block2) shouldBe 'success - if (verifyTransactions) { - getBestFullBlockEncodedId shouldBe Some(chain2block2.header.encodedId) - } - - getBestHeaderOpt shouldBe Some(chain2block2.header) - getRootHash shouldBe Algos.encode(chain2block2.header.stateRoot) - } - - private val t17 = TestCase("apply invalid genesis header") { fixture => - import fixture._ - val (us, bh) = createUtxoState(fixture.settings) - val header = validFullBlock(None, us, bh).header.copy(parentId = bytesToId(Array.fill(32)(9: Byte))) - - getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - - subscribeEvents(classOf[RecoverableFailedModification]) - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - - nodeViewHolderRef ! LocallyGeneratedModifier(header) - expectMsgType[SyntacticallyFailedModification] - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight - getHeightOf(header.id) shouldBe None - } - - private val t18 = TestCase("apply syntactically invalid genesis block") { fixture => - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - - val validBlock = validFullBlock(parentOpt = None, us, bh) - val invalidBlock = validBlock.copy(header = validBlock.header.copy(parentId = bytesToId(Array.fill(32)(9: Byte)))) - - applyBlock(invalidBlock) shouldBe 'failure - getBestFullBlockOpt shouldBe None - getBestHeaderOpt shouldBe None - } - - private val t19 = TestCase("apply semantically invalid genesis block") { fixture => - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - val wusGenesis = WrappedUtxoState(us, bh, fixture.settings, parameters) - - val invalidBlock = generateInvalidFullBlock(None, wusGenesis) - - if (verifyTransactions) { - - val initDigest = getCurrentState.rootDigest - - applyBlock(invalidBlock) shouldBe 'success - - getBestFullBlockOpt shouldBe None - getBestHeaderOpt shouldBe None - getCurrentState.rootDigest shouldEqual initDigest - } - } - - val cases: List[TestCase] = List(t0, t1, t2, t3, t3a, t4, t5, t6, t7, t8, t9) - - NodeViewTestConfig.allConfigs.foreach { c => - cases.foreach { t => - property(s"${t.name} - $c") { - t.run(parameters, c) - } - } - } - - val verifyingTxCases: List[TestCase] = List(t10, t11, t12, t13) - - NodeViewTestConfig.verifyTxConfigs.foreach { c => - verifyingTxCases.foreach { t => - property(s"${t.name} - $c") { - t.run(parameters, c) - } - } - } - - val genesisIdTestCases = List(t14, t15, t16, t17, t18, t19) - - def genesisIdConfig(expectedGenesisIdOpt: Option[ModifierId])(protoSettings: ErgoSettings): ErgoSettings = { - protoSettings.copy(chainSettings = protoSettings.chainSettings.copy(genesisId = expectedGenesisIdOpt)) - } - - genesisIdTestCases.foreach { t => - property(t.name) { - t.run(parameters, NodeViewTestConfig(StateType.Digest, verifyTransactions = true, popowBootstrap = true)) - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala deleted file mode 100644 index 621a2119dd..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala +++ /dev/null @@ -1,87 +0,0 @@ -package org.ergoplatform.nodeView.viewholder - -import akka.actor.ActorRef -import org.ergoplatform.mining.DefaultFakePowScheme -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.nodeView.state.{DigestState, StateType} -import org.ergoplatform.settings.{ErgoSettings, VotingSettings} -import org.ergoplatform.utils.fixtures.NodeViewFixture -import org.ergoplatform.utils.{ErgoPropertyTest, NodeViewTestOps} -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier -import scorex.testkit.utils.NoShrink - -import scala.concurrent.duration._ - -/** - * Test how node view holder is working in pruned mode - */ -class PrunedNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps with NoShrink { - private val BlockInterval = 2.minutes - - def prunedSettings(blocksToKeep: Int): ErgoSettings = { - val defaultSettings = ErgoSettings.read() - defaultSettings.copy( - chainSettings = defaultSettings.chainSettings.copy( - powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n), - voting = VotingSettings(10, 10, 10, 10000, "01"), - blockInterval = BlockInterval - ), - nodeSettings = defaultSettings.nodeSettings.copy( - stateType = StateType.Digest, - verifyTransactions = true, - blocksToKeep = blocksToKeep - ) - ) - } - - def genFullChain(genesisState: WrappedUtxoState, howMany: Int, nodeViewHolderRef: ActorRef): Seq[ErgoFullBlock] = { - (1 to howMany).foldLeft((Seq[ErgoFullBlock](), genesisState, None: Option[ErgoFullBlock])) { case ((chain, wus, parentOpt), h) => - val time = System.currentTimeMillis() - (howMany - h) * (BlockInterval.toMillis * 20) - val block = validFullBlock(parentOpt, wus, time) - val newState = wus.applyModifier(block)(mod => nodeViewHolderRef ! mod).get - (chain :+ block, newState, Some(block)) - }._1 - } - - private def testCode(fixture: NodeViewFixture, toSkip: Int, totalBlocks: Int = 20) = { - import fixture._ - - val (us, bh) = createUtxoState(fixture.settings) - val wus = WrappedUtxoState(us, bh, fixture.settings, parameters) - - val fullChain = genFullChain(wus, totalBlocks, nodeViewHolderRef) - - fullChain.foreach { block => - applyHeader(block.header).isSuccess shouldBe true - } - - fullChain.takeRight(totalBlocks - toSkip).foreach { block => - block.blockSections.foreach { section => - nodeViewHolderRef ! LocallyGeneratedModifier(section) - Thread.sleep(50) - } - } - - val state = getCurrentState.asInstanceOf[DigestState] - state.version shouldBe fullChain.last.id - state.stateContext.lastHeaderOpt.get.id shouldBe fullChain.last.header.id - } - - property(s"pruned chain bootstrapping - blocksToKeep = -1 - all the blocks are to be applied to the state") { - new NodeViewFixture(prunedSettings(-1), parameters).apply(f => testCode(f, 0)) - } - - property(s"pruned chain bootstrapping - blocksToKeep = 3 - first 9 blocks out of 20 are not to be applied to the state") { - new NodeViewFixture(prunedSettings(3), parameters).apply(f => testCode(f, 9)) - } - - property(s"pruned chain bootstrapping - blocksToKeep = 15 - all the blocks are to be applied to the state") { - new NodeViewFixture(prunedSettings(15), parameters).apply(f => testCode(f, 0)) - } - - property(s"pruned chain bootstrapping - total = 30, blocksToKeep = 15 - first 9 blocks are not to be applied to the state") { - new NodeViewFixture(prunedSettings(15), parameters).apply(f => testCode(f, 9, 30)) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala deleted file mode 100644 index c492591ac0..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletServiceSpec.scala +++ /dev/null @@ -1,345 +0,0 @@ -package org.ergoplatform.nodeView.wallet - -import org.ergoplatform.ErgoBox.{NonMandatoryRegisterId, R1} -import org.ergoplatform._ -import org.ergoplatform.db.DBSpec -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPoolReader -import org.ergoplatform.nodeView.wallet.WalletScanLogic.ScanResults -import org.ergoplatform.nodeView.wallet.persistence.{OffChainRegistry, WalletRegistry, WalletStorage} -import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequest, PaymentRequest} -import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanRequest, ScanWalletInteraction} -import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.fixtures.WalletFixture -import org.ergoplatform.utils.generators.ErgoTransactionGenerators -import org.ergoplatform.utils.{ErgoPropertyTest, MempoolTestHelpers, WalletTestOps} -import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} -import org.ergoplatform.wallet.boxes.BoxSelector.BoxSelectionResult -import org.ergoplatform.wallet.boxes.{ErgoBoxSerializer, ReplaceCompactCollectBoxSelector, TrackedBox} -import org.ergoplatform.wallet.crypto.ErgoSignature -import org.ergoplatform.wallet.interface4j.SecretString -import org.ergoplatform.wallet.mnemonic.Mnemonic -import org.scalacheck.Gen -import org.scalatest.BeforeAndAfterAll -import scorex.db.{LDBKVStore, LDBVersionedStore} -import scorex.util.encode.Base16 -import sigmastate.Values.{ByteArrayConstant, EvaluatedValue} -import sigmastate.eval.Extensions.ArrayOps -import sigmastate.helpers.TestingHelpers.testBox -import sigmastate.{SType, Values} - -import scala.collection.compat.immutable.ArraySeq -import scala.util.Random - -class ErgoWalletServiceSpec - extends ErgoPropertyTest - with MempoolTestHelpers - with WalletTestOps - with ErgoWalletSupport - with ErgoTransactionGenerators - with DBSpec - with BeforeAndAfterAll { - - override val ergoSettings: ErgoSettings = settings - - private implicit val x: WalletFixture = new WalletFixture(settings, parameters, getCurrentView(_).vault) - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 4, sizeRange = 4) - private lazy val pks = getPublicKeys.toList - private val masterKey = ExtendedSecretKey.deriveMasterKey(Mnemonic.toSeed(SecretString.create("edge talent poet tortoise trumpet dose")), usePre1627KeyDerivation = false) - - override def afterAll(): Unit = try super.afterAll() finally x.stop() - - private def initialState(store: LDBKVStore, versionedStore: LDBVersionedStore, mempool: Option[ErgoMemPoolReader] = None) = { - ErgoWalletState( - new WalletStorage(store, settings), - secretStorageOpt = Option.empty, - new WalletRegistry(versionedStore)(settings.walletSettings), - OffChainRegistry.empty, - outputsFilter = Option.empty, - WalletVars(Some(defaultProver), Seq.empty, None), - stateReaderOpt = Option.empty, - mempoolReaderOpt = mempool, - utxoStateReaderOpt = Option.empty, - parameters, - maxInputsToUse = 1000, - rescanInProgress = false - ) - } - - property("restoring wallet should fail if pruning is enabled") { - withVersionedStore(2) { versionedStore => - withStore { store => - val walletState = initialState(store, versionedStore) - val walletService = new ErgoWalletServiceImpl(settings) - val settingsWithPruning = settings.copy(nodeSettings = settings.nodeSettings.copy(blocksToKeep = 0)) - walletService.restoreWallet( - walletState, - settingsWithPruning, - mnemonic = SecretString.create("x"), - mnemonicPassOpt = None, - walletPass = SecretString.create("y"), - usePre1627KeyDerivation = false - ).failed.get.getMessage shouldBe "Unable to restore wallet when pruning is enabled" - } - } - } - - property("it should prepare unsigned transaction") { - val inputBoxes = { - Seq( - TrackedBox( - ErgoLikeTransaction(IndexedSeq(), IndexedSeq()), - creationOutIndex = 0, - None, - testBox(1L, Values.TrueLeaf.toSigmaProp, 0), - Set(PaymentsScanId) - ) - ) - } - - forAll(ergoBoxCandidateGen, ergoBoxCandidateGen, validErgoTransactionGen, proveDlogGen) { - case (outputCandidate, outputChangeCandidate, (ergoBoxes, _), proveDlog) => - val selectionResult = new BoxSelectionResult(inputBoxes, Seq(outputChangeCandidate), None) - val tx = prepareUnsignedTransaction(Seq(outputCandidate), startHeight, selectionResult, ergoBoxes, Option(proveDlog)).get - tx.inputs shouldBe inputBoxes.map(_.box.id).map(id => new UnsignedInput(id)) - tx.dataInputs shouldBe ergoBoxes.map(dataInputBox => DataInput(dataInputBox.id)) - tx.outputCandidates.size shouldBe 2 - tx.outputCandidates.map(_.value).sum shouldBe outputCandidate.value + outputChangeCandidate.value - - val txWithChangeBoxesButNoChangeAddress = - prepareUnsignedTransaction(Seq(outputCandidate), startHeight, selectionResult, ergoBoxes, Option.empty) - txWithChangeBoxesButNoChangeAddress.isFailure shouldBe true - } - } - - property("it should generate valid box candidates from payment request") { - forAll(validErgoTransactionGen) { - case (ergoBoxes, _) => - val paymentRequest = PaymentRequest(pks.head, 1, Seq.empty, Map.empty) - val paymentCandidates = requestsToBoxCandidates(Seq(paymentRequest), ergoBoxes.head.id, startHeight, parameters, pks).get - paymentCandidates shouldBe List(new ErgoBoxCandidate(value = 1, ergoTree = pks.head.script, startHeight)) - } - } - - property("it should generate valid box candidates from asset issue requests") { - forAll(validErgoTransactionGen) { - case (ergoBoxes, _) => - val ergoBox = ergoBoxes.head - - val registers: Option[Map[NonMandatoryRegisterId, EvaluatedValue[_ <: SType]]] = Option(Map(ErgoBox.R4 -> sigmastate.Values.FalseLeaf)) - val illegalAssetIssueRequest = AssetIssueRequest(address = pks.head, Some(1), amount = 1, "test", "test", 4, registers) - val invalidCandidates = requestsToBoxCandidates(Seq(illegalAssetIssueRequest), ergoBox.id, startHeight, parameters, pks) - invalidCandidates.failed.get.getMessage shouldBe "Additional registers contain R0...R6" - - val assetIssueRequestWithoutAddress = AssetIssueRequest(addressOpt = Option.empty, Some(1), amount = 1, "test", "test", 4, Option.empty) - val missingAddressCandidates = requestsToBoxCandidates(Seq(assetIssueRequestWithoutAddress), ergoBox.id, startHeight, parameters, Seq.empty) - missingAddressCandidates.failed.get.getMessage shouldBe "No address available for box locking" - - val assetIssueRequestWithoutValue = AssetIssueRequest(address = pks.head, valueOpt = Option.empty, amount = 1, "test", "test", 4, Option.empty) - val missingValueCandidates = requestsToBoxCandidates(Seq(assetIssueRequestWithoutValue), ergoBox.id, startHeight, parameters, Seq.empty).get.head - missingValueCandidates.value > 0 shouldBe true - - val assetIssueRequest = AssetIssueRequest(address = pks.head, Some(1), amount = 1, "test-name", "test-description", 4, Option.empty) - val validCandidate = requestsToBoxCandidates(Seq(assetIssueRequest), ergoBox.id, startHeight, parameters, Seq.empty).get.head - validCandidate.value shouldBe 1 - validCandidate.additionalRegisters shouldBe - Map( - ErgoBox.R4 -> ByteArrayConstant("test-name".getBytes("UTF-8")), - ErgoBox.R5 -> ByteArrayConstant("test-description".getBytes("UTF-8")), - ErgoBox.R6 -> ByteArrayConstant("4".getBytes("UTF-8")), - ) - validCandidate.additionalTokens.toArray.toMap shouldBe Map(ergoBox.id.toColl -> 1) - validCandidate.creationHeight shouldBe startHeight - validCandidate.ergoTree shouldBe pks.head.script - } - } - - property("it should get scan confirmed and unconfirmed transactions") { - forAll(Gen.nonEmptyListOf(trackedBoxGen), modifierIdGen) { case (boxes, txId) => - withVersionedStore(10) { versionedStore => - withStore { store => - val allBoxes = { - val unspentBoxes = boxes.map(bx => bx.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = Set(ScanId @@ 0.shortValue()))) - val spentBox = boxes.head.copy(spendingHeightOpt = Some(100), spendingTxIdOpt = Some(txId), scans = Set(ScanId @@ 0.shortValue())) - unspentBoxes :+ spentBox - } - val encodedBoxes = allBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box.box)) - } - - val paymentRequest = PaymentRequest(pks.head, 50000, Seq.empty, Map.empty) - val boxSelector = new ReplaceCompactCollectBoxSelector(settings.walletSettings.maxInputs, settings.walletSettings.optimalInputs, None) - - val walletService = new ErgoWalletServiceImpl(ergoSettings) - val unconfirmedTx = UnconfirmedTransaction( - walletService.generateTransaction( - initialState(store, versionedStore), - boxSelector, - Seq(paymentRequest), - inputsRaw = encodedBoxes, - dataInputsRaw = Seq.empty, - sign = true - ).get.asInstanceOf[ErgoTransaction], None) - - // let's create wallet state with an unconfirmed transaction in mempool - val wState = initialState(store, versionedStore, Some(new FakeMempool(Seq(unconfirmedTx)))) - val signedTx1 = - walletService.generateTransaction(wState, boxSelector, Seq(paymentRequest), inputsRaw = encodedBoxes, dataInputsRaw = Seq.empty, sign = true) - .get.asInstanceOf[ErgoTransaction] - val walletTx1 = WalletTransaction(signedTx1, 100, Seq(ScanId @@ 0.shortValue())) - - // let's update wallet registry with a transaction from a block - val genesisBlock = makeGenesisBlock(pks.head.pubkey, randomNewAsset) - wState.registry.updateOnBlock(ScanResults(allBoxes, ArraySeq.empty, Seq(walletTx1)), genesisBlock.id, blockHeight = 100).get - - // transaction should be retrieved by only a scan id that was associated with it - val txs1 = walletService.getScanTransactions(wState, ScanId @@ 0.shortValue(), 100) - assert(txs1.nonEmpty) - val txs2 = walletService.getScanTransactions(wState, ScanId @@ 1.shortValue(), 100) - assert(txs2.isEmpty) - - // let's test that unconfirmed transaction is retrieved - val scanId = - walletService.addScan(wState, ScanRequest("foo", EqualsScanningPredicate(R1, ByteArrayConstant(pks.head.script.bytes)), Some(ScanWalletInteraction.Off), Some(false))) - .get._1.scanId - - val txs3 = walletService.getScanTransactions(wState, scanId, 100, includeUnconfirmed = true) - txs3.size shouldBe 1 - - txs3.head.wtx.tx.id shouldBe unconfirmedTx.transaction.id - } - } - } - } - - property("it should get spent and unspent wallet boxes") { - forAll(Gen.nonEmptyListOf(trackedBoxGen), modifierIdGen) { case (boxes, txId) => - withVersionedStore(10) { versionedStore => - withStore { store => - val wState = initialState(store, versionedStore) - val blockId = modifierIdGen.sample.get - val unspentBoxes = boxes.map(bx => bx.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = Set(PaymentsScanId))) - val spentBox = boxes.head.copy(spendingHeightOpt = Some(10000), spendingTxIdOpt = Some(txId), scans = Set(PaymentsScanId)) - val allBoxes = unspentBoxes :+ spentBox - wState.registry.updateOnBlock(ScanResults(allBoxes, ArraySeq.empty, ArraySeq.empty), blockId, 100).get - - val walletService = new ErgoWalletServiceImpl(settings) - val actualUnspentOnlyWalletBoxes = walletService.getWalletBoxes(wState, unspentOnly = true, considerUnconfirmed = false).toList - val expectedUnspentOnlyWalletBoxes = unspentBoxes.map(x => WalletBox(x, wState.fullHeight)).sortBy(_.trackedBox.inclusionHeightOpt) - actualUnspentOnlyWalletBoxes should contain theSameElementsAs expectedUnspentOnlyWalletBoxes - - val actualWalletBoxes = walletService.getWalletBoxes(wState, unspentOnly = false, considerUnconfirmed = false).toList - val expectedWalletBoxes = allBoxes.map(x => WalletBox(x, wState.fullHeight)).sortBy(_.trackedBox.inclusionHeightOpt) - actualWalletBoxes should contain theSameElementsAs expectedWalletBoxes - } - } - } - } - - property("it should generate signed and unsigned transaction") { - withVersionedStore(2) { versionedStore => - withStore { store => - val wState = initialState(store, versionedStore) - - val encodedBoxes = - boxesAvailable(makeGenesisBlock(pks.head.pubkey, randomNewAsset), pks.head.pubkey) - .map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - val paymentRequest = PaymentRequest(pks.head, 50000, Seq.empty, Map.empty) - val boxSelector = new ReplaceCompactCollectBoxSelector(settings.walletSettings.maxInputs, settings.walletSettings.optimalInputs, None) - - val (tx, inputs, dataInputs) = generateUnsignedTransaction(wState, boxSelector, Seq(paymentRequest), inputsRaw = encodedBoxes, dataInputsRaw = Seq.empty).get - dataInputs shouldBe empty - inputs.size shouldBe 1 - tx.inputs.size shouldBe 1 - tx.outputs.size shouldBe 2 - tx.outputs.map(_.value).sum shouldBe inputs.map(_.value).sum - - val walletService = new ErgoWalletServiceImpl(settings) - val signedTx = walletService.generateTransaction(wState, boxSelector, Seq(paymentRequest), inputsRaw = encodedBoxes, dataInputsRaw = Seq.empty, sign = true).get.asInstanceOf[ErgoTransaction] - - ErgoSignature.verify(signedTx.messageToSign, signedTx.inputs.head.spendingProof.proof, pks.head.pubkey.value) shouldBe true - signedTx.inputs.size shouldBe 1 - signedTx.outputs.size shouldBe 2 - - } - } - } - - property("it should process unlock using preEip3Derivation") { - withVersionedStore(2) { versionedStore => - withStore { store => - val walletState = initialState(store, versionedStore) - val unlockedWalletState = processUnlock(walletState, masterKey, usePreEip3Derivation = true).get - unlockedWalletState.storage.readAllKeys().size shouldBe 1 - unlockedWalletState.storage.readAllKeys() should contain(masterKey.publicKey) - unlockedWalletState.walletVars.proverOpt shouldNot be(empty) - } - } - } - - property("it should process unlock without preEip3Derivation") { - withVersionedStore(2) { versionedStore => - withStore { store => - val walletState = initialState(store, versionedStore) - val unlockedWalletState = processUnlock(walletState, masterKey, usePreEip3Derivation = false).get - unlockedWalletState.storage.readAllKeys().size shouldBe 1 - unlockedWalletState.storage.readChangeAddress shouldNot be(empty) - unlockedWalletState.walletVars.proverOpt shouldNot be(empty) - } - } - } - - property("it should lock/unlock wallet") { - withVersionedStore(2) { versionedStore => - withStore { store => - val walletState = initialState(store, versionedStore) - val walletService = new ErgoWalletServiceImpl(settings) - val pass = Random.nextString(10) - val initializedState = walletService.initWallet(walletState, settings, SecretString.create(pass), Option.empty).get._2 - - // Wallet unlocked after init, so we're locking it - val initLockedWalletState = walletService.lockWallet(initializedState) - initLockedWalletState.secretStorageOpt.get.isLocked shouldBe true - initLockedWalletState.walletVars.proverOpt shouldBe empty - - val unlockedWalletState = walletService.unlockWallet(initLockedWalletState, SecretString.create(pass), usePreEip3Derivation = true).get - unlockedWalletState.secretStorageOpt.get.isLocked shouldBe false - unlockedWalletState.storage.readAllKeys().size shouldBe 1 - unlockedWalletState.walletVars.proverOpt shouldNot be(empty) - - val lockedWalletState = walletService.lockWallet(unlockedWalletState) - lockedWalletState.secretStorageOpt.get.isLocked shouldBe true - lockedWalletState.walletVars.proverOpt shouldBe empty - - val finalUnlockedState = walletService.unlockWallet(lockedWalletState, SecretString.create(pass), usePreEip3Derivation = true).get - finalUnlockedState.secretStorageOpt.get.isLocked shouldBe false - finalUnlockedState.storage.readAllKeys().size shouldBe 1 - finalUnlockedState.walletVars.proverOpt shouldNot be(empty) - } - } - } - - property("it should derive private key correctly") { - withVersionedStore(2) { versionedStore => - withStore { store => - - val pass = SecretString.create(Random.nextString(10)) - val mnemonic = "edge talent poet tortoise trumpet dose" - - val walletService = new ErgoWalletServiceImpl(settings) - val ws1 = initialState(store, versionedStore) - val ws2 = walletService.initWallet(ws1, settings, pass, Some(SecretString.create(mnemonic))).get._2 - ws2.secretStorageOpt.get.unlock(pass) - - val path = DerivationPath.fromEncoded("m/44/1/1/0/0").get - val sk = ws2.secretStorageOpt.get.secret.get - val pk = sk.derive(path).publicKey - - walletService.getPrivateKeyFromPath(ws2, pk.path).get.w shouldBe sk.derive(path).privateInput.w - } - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala deleted file mode 100644 index 5f5967d4d3..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/ErgoWalletSpec.scala +++ /dev/null @@ -1,1123 +0,0 @@ -package org.ergoplatform.nodeView.wallet - -import org.ergoplatform._ -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} -import org.ergoplatform.nodeView.wallet.IdUtils._ -import org.ergoplatform.nodeView.wallet.persistence.{WalletDigest, WalletDigestSerializer} -import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequest, BurnTokensRequest, ExternalSecret, PaymentRequest} -import org.ergoplatform.sdk.wallet.secrets.PrimitiveSecretKey -import org.ergoplatform.settings.{Algos, Constants} -import org.ergoplatform.utils._ -import org.ergoplatform.utils.fixtures.WalletFixture -import org.ergoplatform.wallet.boxes.BoxSelector.MinBoxValue -import org.ergoplatform.wallet.boxes.ErgoBoxSerializer -import org.ergoplatform.wallet.interpreter.{ErgoInterpreter, TransactionHintsBag} -import org.scalacheck.Gen -import org.scalatest.concurrent.Eventually -import scorex.util.ModifierId -import scorex.util.encode.Base16 -import sigmastate.crypto.DLogProtocol.DLogProverInput -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.{CAND, CTHRESHOLD} - -import scala.concurrent.duration._ - -class ErgoWalletSpec extends ErgoPropertyTest with WalletTestOps with Eventually { - - private implicit val verifier: ErgoInterpreter = ErgoInterpreter(parameters) - - property("assets in WalletDigest are deterministic against serialization") { - forAll(Gen.listOfN(5, assetGen)) { preAssets => - val assets = preAssets.map { case (id, amt) => ModifierId @@ Algos.encode(id) -> amt } - val wd0 = WalletDigest(1, 0, assets) - val bs = WalletDigestSerializer.toBytes(wd0) - WalletDigestSerializer.parseBytes(bs).walletAssetBalances shouldBe wd0.walletAssetBalances - } - } - - property("do not use inputs spent in off-chain transaction") { - withFixture { implicit w => - val addresses = getPublicKeys - val pubkey = addresses.head.pubkey - addresses.length should be > 0 - val genesisBlock = makeGenesisBlock(pubkey, randomNewAsset) - val genesisTx = genesisBlock.transactions.head - applyBlock(genesisBlock) shouldBe 'success //scan by wallet happens during apply - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val tx = - eventually { - val snap = getConfirmedBalances - // prepare a lot of inputs - val inputsToCreate = 50 - val sumToSpend = (snap.walletBalance - MinBoxValue) / (inputsToCreate + 1) - val req = (0 until inputsToCreate).map(_ => PaymentRequest(addresses.head, sumToSpend, Seq.empty, Map.empty)) - log.info(s"Confirmed balance $snap") - log.info(s"Payment request $req") - val tx = await(wallet.generateTransaction(req)).get - log.info(s"Generated transaction $tx") - val context = new ErgoStateContext(Seq(genesisBlock.header), Some(genesisBlock.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty) - val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get) - tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success - val block = makeNextBlock(getUtxoState, Seq(tx)) - applyBlock(block) shouldBe 'success //scan by wallet happens during apply - tx - } - val (req2, tx2) = - eventually { - // generate transaction spending part of inputs - val newSumToSpend = tx.outputs.head.value - val req2 = Seq(PaymentRequest(addresses.head, newSumToSpend, Seq.empty, Map.empty)) - log.info(s"Payment requests 2 $req2") - val tx2 = await(wallet.generateTransaction(req2)).get - (req2, tx2) - } - log.info(s"Generated transaction $tx2") - wallet.scanOffchain(tx2) - - eventually { - tx2.inputs.size should be < tx.outputs.size - // trying to create a new transaction - val tx3 = await(wallet.generateTransaction(req2)).get - // check that tx3 has inputs different from tx2 - tx3.inputs.foreach { in => - tx2.inputs.exists(tx2In => tx2In.boxId sameElements in.boxId) shouldBe false - } - } - } - } - - property("Generate asset issuing transaction") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey) - val genesisTx = genesisBlock.transactions.head - applyBlock(genesisBlock) shouldBe 'success //scan by wallet happens during apply - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 100.millis) - eventually { - val availableAmount = getConfirmedBalances.walletBalance - val emissionAmount: Int = 100000000 - val tokenName: String = "ERG" - val tokenDescription: String = s"ERG description" - val tokenDecimals: Int = 9 - val feeAmount = availableAmount / 4 - val feeReq = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), feeAmount, Seq.empty, Map.empty) - val req = AssetIssueRequest(address, None, emissionAmount, tokenName, tokenDescription, tokenDecimals) - val tx = await(wallet.generateTransaction(Seq(feeReq, req))).get - log.info(s"Generated transaction $tx") - val context = new ErgoStateContext( - Seq(genesisBlock.header), - Some(genesisBlock.extension), - startDigest, - parameters, - validationSettingsNoIl, - VotingData.empty) - val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get) - tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success - } - } - } - - property("Generate transaction with user-defined input") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance, assetToSpend, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 1 - tx1.outputs.head.value shouldBe confirmedBalance - toAssetMap(tx1.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - - //change == 1: - val assetToSpend2 = assetToSpend.map { case (tokenId, tokenValue) => (tokenId, tokenValue - 1) } - val assetToReturn = assetToSpend.map { case (tokenId, _) => (tokenId, 1L) } - val req2 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance - MinBoxValue, assetToSpend2, Map.empty) - - val tx2 = await(wallet.generateTransaction(Seq(req2))).get - tx2.outputs.size shouldBe 2 - tx2.outputs.head.value shouldBe confirmedBalance - MinBoxValue - toAssetMap(tx2.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend2) - tx2.outputs(1).value shouldBe MinBoxValue - toAssetMap(tx2.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(assetToReturn) - } - } - } - - property("Generate transaction with BurnTokensRequest") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance, assetToSpend, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 1 - tx1.outputs.head.value shouldBe confirmedBalance - toAssetMap(tx1.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - - //change == 1: - val assetToSpend2 = assetToSpend.map { case (tokenId, tokenValue) => (tokenId, tokenValue - 1) } - val assetToReturn = assetToSpend.map { case (tokenId, _) => (tokenId, 1L) } - val req2 = Seq(BurnTokensRequest(assetToSpend2)) - - val tx2 = await(wallet.generateTransaction(req2)).get - tx2.outputs.size shouldBe 1 - tx2.outputs.head.value shouldBe confirmedBalance - toAssetMap(tx2.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToReturn) - } - } - } - - property("Generate transaction with PaymentRequest (no tokens) and BurnTokensRequest") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - log.error(s"Confirmed balance $confirmedBalance") - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance, assetToSpend, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 1 - tx1.outputs.head.value shouldBe confirmedBalance - toAssetMap(tx1.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - - //change == 1: - val assetToSpend2 = assetToSpend.map { case (tokenId, tokenValue) => (tokenId, tokenValue - 1) } - val assetToReturn = assetToSpend.map { case (tokenId, _) => (tokenId, 1L) } - val req2 = Seq(BurnTokensRequest(assetToSpend2), PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance - MinBoxValue, Seq.empty, Map.empty)) - - val tx2 = await(wallet.generateTransaction(req2)).get - tx2.outputs.size shouldBe 2 - tx2.outputs.head.value shouldBe confirmedBalance - MinBoxValue - toAssetMap(tx2.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(Seq.empty) - tx2.outputs(1).value shouldBe MinBoxValue - toAssetMap(tx2.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(assetToReturn) - } - } - } - - property("whitelist set, preserve tokens from auto-burn") { - val inputs = { - val x = IndexedSeq(new Input(genesisEmissionBox.id, emptyProverResult)) - Seq(encodedTokenId(x.head.boxId.toTokenId)) - } - - implicit val ww: WalletFixture = new WalletFixture(settings - .copy(walletSettings = settings - .walletSettings.copy(tokensWhitelist = Some(inputs))), parameters, getCurrentView(_).vault) - - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeNextBlock(getUtxoState, Seq(makeGenesisTxWithAsset(pubKey, issueAsset = true))) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - val assetR = assetsByTokenId(initialBoxes).toSeq - Some(assetR.map(x => encodedTokenId(x._1))) shouldBe ww.settings.walletSettings.tokensWhitelist - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - log.error(s"Confirmed balance $confirmedBalance") - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - Some(assetToSpend.map(x => encodedTokenId(x._1))) shouldBe ww.settings.walletSettings.tokensWhitelist - assetToSpend should not be empty - - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance / 2, Seq.empty, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 2 - tx1.outputs.head.value shouldBe (confirmedBalance / 2) - tx1.outputs.head.additionalTokens.toArray shouldBe Seq.empty - toAssetMap(tx1.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - } - } - - property("whitelist empty, auto-burn tokens on arbitrary tx") { - implicit val ww: WalletFixture = new WalletFixture(settings - .copy(walletSettings = settings - .walletSettings.copy(tokensWhitelist = Some(Seq.empty))), parameters, getCurrentView(_).vault) - - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeNextBlock(getUtxoState, Seq(makeGenesisTxWithAsset(pubKey, issueAsset = true))) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - log.error(s"Confirmed balance $confirmedBalance") - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance / 2, Seq.empty, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 2 - tx1.outputs.head.value shouldBe (confirmedBalance / 2) - tx1.outputs.head.additionalTokens.toArray shouldBe Seq.empty - toAssetMap(tx1.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(Seq.empty) - } - } - - property("whitelist not set, ignore auto-burn") { - implicit val ww: WalletFixture = new WalletFixture(settings - .copy(walletSettings = settings - .walletSettings.copy(tokensWhitelist = None)), parameters, getCurrentView(_).vault) - - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeNextBlock(getUtxoState, Seq(makeGenesisTxWithAsset(pubKey, issueAsset = true))) - val initialBoxes = boxesAvailable(genesisBlock, pubKey) - - val boxesToUseEncoded = initialBoxes.map { box => - Base16.encode(ErgoBoxSerializer.toBytes(box)) - } - - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - log.error(s"Confirmed balance $confirmedBalance") - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance / 2, Seq.empty, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1), boxesToUseEncoded)).get - tx1.outputs.size shouldBe 2 - tx1.outputs.head.value shouldBe (confirmedBalance / 2) - tx1.outputs.head.additionalTokens.toArray shouldBe Seq.empty - toAssetMap(tx1.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - } - } - - property("Generate transaction with multiple inputs") { - withFixture { implicit w => - val addresses = getPublicKeys - val pubkey = addresses.head.pubkey - addresses.length should be > 0 - val genesisBlock = makeGenesisBlock(pubkey, randomNewAsset) - val genesisTx = genesisBlock.transactions.head - val initialBoxes = boxesAvailable(genesisTx, pubkey) - applyBlock(genesisBlock) shouldBe 'success //scan by wallet happens during apply - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val (tx, block, assetsToSpend) = - eventually { - val snap = getConfirmedBalances - val assetsToSpend = assetsByTokenId(initialBoxes).toSeq - assetsToSpend should not be empty - - val sumToSpend = snap.walletBalance / (addresses.length + 1) - val req = - PaymentRequest(addresses.head, sumToSpend, assetsToSpend, Map.empty) +: - addresses.tail.map(a => PaymentRequest(a, sumToSpend, Seq.empty, Map.empty)) - log.info(s"Confirmed balance $snap") - log.info(s"Payment request $req") - val tx = await(wallet.generateTransaction(req)).get - log.info(s"Generated transaction $tx") - val context = new ErgoStateContext( - Seq(genesisBlock.header), - Some(genesisBlock.extension), - startDigest, - parameters, - validationSettingsNoIl, - VotingData.empty) - val boxesToSpend = tx.inputs.map(i => genesisTx.outputs.find(o => java.util.Arrays.equals(o.id, i.boxId)).get) - tx.statefulValidity(boxesToSpend, emptyDataBoxes, context) shouldBe 'success - - val block = makeNextBlock(getUtxoState, Seq(tx)) - applyBlock(block) shouldBe 'success //scan by wallet happens during apply - (tx, block, assetsToSpend) - } - eventually { - val newSnap = getConfirmedBalances - val newSumToSpend = newSnap.walletBalance / addresses.length - val req2 = PaymentRequest(addresses.head, newSumToSpend, assetsToSpend, Map.empty) +: - addresses.tail.map(a => PaymentRequest(a, newSumToSpend, Seq.empty, Map.empty)) - log.info(s"New balance $newSnap") - log.info(s"Payment requests 2 $req2") - val tx2 = await(wallet.generateTransaction(req2)).get - log.info(s"Generated transaction $tx2") - val context2 = new ErgoStateContext(Seq(block.header), Some(block.extension), startDigest, parameters, validationSettingsNoIl, VotingData.empty) - val knownBoxes = tx.outputs ++ genesisTx.outputs - val boxesToSpend2 = tx2.inputs.map(i => knownBoxes.find(o => java.util.Arrays.equals(o.id, i.boxId)).get) - tx2.statefulValidity(boxesToSpend2, emptyDataBoxes, context2) shouldBe 'success - } - } - } - - property("off-chain scan") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.script - - val bs0 = getBalancesWithUnconfirmed - bs0.walletBalance shouldBe 0 - bs0.walletAssetBalances shouldBe empty - - val balance1 = settings.walletSettings.dustLimit.getOrElse(1000000L) + 1 - val box1 = IndexedSeq(new ErgoBoxCandidate(balance1, pubKey, startHeight, randomNewAsset.toColl)) - wallet.scanOffchain(ErgoTransaction(fakeInputs, box1)) - - implicit val patienceConfig: PatienceConfig = PatienceConfig(1.second, 100.millis) - eventually { - val bs1 = getBalancesWithUnconfirmed - bs1.walletBalance shouldBe balance1 - bs1.walletAssetBalances shouldBe assetAmount(box1) - } - - val balance2 = settings.walletSettings.dustLimit.getOrElse(1000000L) + 1 - val box2 = IndexedSeq(new ErgoBoxCandidate(balance2, pubKey, startHeight, randomNewAsset.toColl)) - wallet.scanOffchain(ErgoTransaction(fakeInputs, IndexedSeq(), box2)) - - eventually { - val bs2 = getBalancesWithUnconfirmed - bs2.walletBalance shouldBe (balance1 + balance2) - bs2.walletAssetBalances shouldBe assetAmount(box1 ++ box2) - } - } - } - - property("off-chain box spending") { - withFixture { implicit w => - val address = getPublicKeys.head - val tx = makeGenesisTx(address.pubkey, randomNewAsset) - wallet.scanOffchain(tx) - val boxesToSpend = boxesAvailable(tx, address.pubkey) - val balanceToSpend = balanceAmount(boxesToSpend) - log.info(s"Balance to spent: $balanceToSpend") - implicit val patienceConfig: PatienceConfig = PatienceConfig(offchainScanTime(tx).millis, 100.millis) - val (spendingTx, balanceToReturn, assetsAfterSpending) = - eventually { - val totalBalance = getBalancesWithUnconfirmed.walletBalance - totalBalance shouldEqual balanceToSpend - log.info(s"Total balance with unconfirmed: $totalBalance") - val balanceToReturn = randomLong(balanceToSpend) - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsWithRandom(boxesToSpend)) - val assetsAfterSpending = assetAmount(boxesAvailable(spendingTx, address.pubkey)) - assetsAfterSpending should not be empty - (spendingTx, balanceToReturn, assetsAfterSpending) - } - wallet.scanOffchain(spendingTx) - eventually { - val totalAfterSpending = getBalancesWithUnconfirmed - - log.info(s"Balance to return back: $balanceToReturn") - totalAfterSpending.walletBalance shouldEqual balanceToReturn - totalAfterSpending.walletAssetBalances shouldEqual assetsAfterSpending - } - } - } - - property("off-chain double registration") { - withFixture { implicit w => - val address = getPublicKeys.head - val tx = makeGenesisTx(address.pubkey, randomNewAsset) - wallet.scanOffchain(tx) - val boxesToSpend = boxesAvailable(tx, address.pubkey) - val balanceToSpend = balanceAmount(boxesToSpend) - implicit val patienceConfig: PatienceConfig = PatienceConfig((offchainScanTime(tx) * 3).millis, 100.millis) - val (spendingTx, totalBalance, balanceToReturn, assets) = - eventually { - val totalBalance = getBalancesWithUnconfirmed.walletBalance - - val balanceToReturn = randomLong(balanceToSpend) - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsWithRandom(boxesToSpend)) - // val doubleSpendingTx = makeSpendingTx(boxesToSpend, address, randomLong(balanceToSpend)) - val assets = assetAmount(boxesAvailable(spendingTx, address.pubkey)) - assets should not be empty - (spendingTx, totalBalance, balanceToReturn, assets) - } - wallet.scanOffchain(Seq(spendingTx, spendingTx)) - wallet.scanOffchain(spendingTx) - - log.info(s"Total with unconfirmed balance: $totalBalance") - log.info(s"Balance to spent: $balanceToSpend") - log.info(s"Balance to return back: $balanceToReturn") - eventually { - val totalAfterSpending = getBalancesWithUnconfirmed - totalBalance shouldEqual balanceToSpend - totalAfterSpending.walletBalance shouldEqual balanceToReturn - totalAfterSpending.walletAssetBalances shouldEqual assets - } - } - } - - property("off-chain spending of the on-chain box") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey, randomNewAsset) - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - val sumBalance = balanceAmount(boxesToSpend) - log.info(s"Sum balance: $sumBalance") - val balanceToReturn = randomLong(sumBalance) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val (spendingTx, assets) = - eventually { - val totalBalance = getBalancesWithUnconfirmed.walletBalance - val confirmedBalance = getConfirmedBalances.walletBalance - - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsWithRandom(boxesToSpend)) - val assets = assetAmount(boxesAvailable(spendingTx, address.pubkey)) - assets should not be empty - confirmedBalance shouldBe sumBalance - totalBalance shouldBe sumBalance - log.info(s"Balance before spending: $confirmedBalance") - log.info(s"Total with unconfirmed balance before spending: $totalBalance") - (spendingTx, assets) - } - wallet.scanOffchain(spendingTx) - eventually { - val confirmedAfterSpending = getConfirmedBalances.walletBalance - val totalAfterSpending = getBalancesWithUnconfirmed - - log.info(s"Balance after spending: $confirmedAfterSpending") - log.info(s"Total with unconfirmed after spending: $totalAfterSpending") - - confirmedAfterSpending shouldBe sumBalance - totalAfterSpending.walletBalance shouldBe balanceToReturn - totalAfterSpending.walletAssetBalances shouldBe assets - } - } - } - - property("assets application") { - withFixture { implicit w => - val address = getPublicKeys.head - val asset1Sum = randomLong() - val genesisBlock = makeGenesisBlock(address.pubkey, Seq(newAssetIdStub -> asset1Sum)) - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val (asset1Token, asset1ToReturn, asset2Sum, spendingBlock) = - eventually { - val initialBalance = getConfirmedBalances - val initialTotal = getBalancesWithUnconfirmed - val initialAssets = initialBalance.walletAssetBalances - log.info(s"Initial assets: ${boxesToSpend.flatMap(_.additionalTokens.toArray)}") - log.info(s"Confirmed: $initialBalance") - log.info(s"With unconfirmed: $initialTotal") - initialAssets should not be empty - val (asset1Token, asset1InitialValue) = initialAssets.head - asset1InitialValue shouldBe asset1Sum - initialTotal.walletAssetBalances shouldBe initialAssets - - val asset2Sum = randomLong() - val asset1ToReturn = randomLong(asset1Sum) - val assets2Seq = Seq(decodedTokenId(asset1Token) -> asset1ToReturn, newAssetIdStub -> asset2Sum) - val balanceToReturn = 1000 * parameters.minValuePerByte - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assets2Seq) - val spendingBlock = makeNextBlock(getUtxoState, Seq(spendingTx)) - applyBlock(spendingBlock) shouldBe 'success - (asset1Token, asset1ToReturn, asset2Sum, spendingBlock) - } - wallet.scanPersistent(spendingBlock) - eventually { - val balanceAfterSpending = getConfirmedBalances - val totalAfterSpending = getBalancesWithUnconfirmed - log.info(s"After spending: $balanceAfterSpending") - log.info(s"With unconfirmed after spending: $balanceAfterSpending") - val assets = balanceAfterSpending.walletAssetBalances - totalAfterSpending.walletAssetBalances.toMap shouldBe assets.toMap - assets.find(_._1 == asset1Token).get._2 shouldBe asset1ToReturn - val asset2 = assets.filter(_._1 != asset1Token) - asset2 should not be empty - asset2.head._2 shouldBe asset2Sum - } - } - } - - property("on-chain box spending (without return)") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val (spendingBlock, boxesToSpend, confirmedBalance, balanceToSpend) = - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - val balanceToSpend = balanceAmount(boxesToSpend) - log.info(s"Confirmed balance $confirmedBalance") - log.info(s"Sum balance: $balanceToSpend") - confirmedBalance should be > 0L - confirmedBalance shouldBe balanceToSpend - - val spendingTx = makeSpendingTx(boxesToSpend, address, 0, assetsWithRandom(boxesToSpend)) - - val spendingBlock = makeNextBlock(getUtxoState, Seq(spendingTx)) - applyBlock(spendingBlock) shouldBe 'success - (spendingBlock, boxesToSpend, confirmedBalance, balanceToSpend) - } - wallet.scanPersistent(spendingBlock) - eventually { - val balanceAfterSpending = getConfirmedBalances - log.info(s"Boxes to spend: $boxesToSpend") - log.info(s"Total with unconfirmed balance: $confirmedBalance") - log.info(s"Balance to spent: $balanceToSpend") - log.info(s"Balance after spend: ${balanceAfterSpending.walletBalance}") - balanceAfterSpending.walletBalance shouldEqual 0 - getBalancesWithUnconfirmed shouldEqual balanceAfterSpending - } - } - } - - property("on-chain box spending (with return)") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 300.millis) - val (confirmedBalance, balanceToSpend, balanceToReturn, assets, spendingBlock) = - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - val balanceToSpend = balanceAmount(boxesToSpend) - log.info(s"Boxes to spend: $boxesToSpend") - log.info(s"Confirmed balance $confirmedBalance") - log.info(s"Sum balance: $balanceToSpend") - confirmedBalance should be > 0L - confirmedBalance shouldBe balanceToSpend - - val balanceToReturn = randomLong(balanceToSpend) - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsWithRandom(boxesToSpend)) - val assets = assetAmount(boxesAvailable(spendingTx, address.pubkey)) - assets should not be empty - val spendingBlock = makeNextBlock(getUtxoState, Seq(spendingTx)) - applyBlock(spendingBlock) shouldBe 'success - (confirmedBalance, balanceToSpend, balanceToReturn, assets, spendingBlock) - } - wallet.scanPersistent(spendingBlock) - eventually { - val balanceAfterSpending = getConfirmedBalances - log.info(s"Total with unconfirmed balance: $confirmedBalance") - log.info(s"Balance to spent: $balanceToSpend") - log.info(s"Balance to return back: $balanceToReturn") - balanceAfterSpending.walletBalance shouldEqual (confirmedBalance - balanceToSpend + balanceToReturn) - balanceAfterSpending.walletAssetBalances.toMap shouldBe assets.toMap - - getBalancesWithUnconfirmed.height shouldEqual balanceAfterSpending.height - getBalancesWithUnconfirmed.walletBalance shouldEqual balanceAfterSpending.walletBalance - getBalancesWithUnconfirmed.walletAssetBalances.toMap shouldEqual balanceAfterSpending.walletAssetBalances.toMap - } - } - } - - property("off-chain transaction becomes on-chain") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val tx = makeGenesisTx(pubKey, randomNewAsset) - wallet.scanOffchain(tx) - implicit val patienceConfig: PatienceConfig = PatienceConfig(offchainScanTime(tx).millis, 100.millis) - val (initialBalance, sumBalance, sumAssets) = - eventually { - val boxesToSpend = boxesAvailable(tx, pubKey) - val sumBalance = balanceAmount(boxesToSpend) - val sumAssets = assetAmount(boxesToSpend) - sumAssets should not be empty - - val initialBalance = getBalancesWithUnconfirmed.walletBalance - initialBalance shouldBe sumBalance - - val block = makeNextBlock(getUtxoState, Seq(tx)) - applyBlock(block) shouldBe 'success - (initialBalance, sumBalance, sumAssets) - } - - eventually { - val confirmedBalance = getConfirmedBalances - log.info(s"Confirmed balance $confirmedBalance") - log.info(s"Sum balance: $sumBalance") - initialBalance shouldBe sumBalance - confirmedBalance.walletBalance should be > 0L - confirmedBalance.walletBalance shouldBe initialBalance - confirmedBalance.walletAssetBalances shouldBe sumAssets - getBalancesWithUnconfirmed shouldBe confirmedBalance - } - - } - } - - property("off-chain spending rollback") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey) - val initialBoxes = boxesAvailable(genesisBlock, address.pubkey) - val initialBalance = balanceAmount(initialBoxes) - applyBlock(genesisBlock) shouldBe 'success - val initialState = getCurrentState - - // We need this second block to have something to rollback. Just spent some balance to anyone - val balanceToSpend = randomLong(initialBalance) - val onchainSpendingTx = makeTx(initialBoxes, emptyProverResult, balanceToSpend, address.pubkey) - val boxesToSpend = boxesAvailable(onchainSpendingTx, address.pubkey) - val block = makeNextBlock(getUtxoState, Seq(onchainSpendingTx)) - applyBlock(block) shouldBe 'success - wallet.scanPersistent(block) - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - val confirmedBalance = - eventually { - val totalBalance = getBalancesWithUnconfirmed.walletBalance - val confirmedBalance = getConfirmedBalances.walletBalance - - confirmedBalance shouldBe balanceToSpend - totalBalance shouldBe confirmedBalance - log.info(s"Initial balance: $initialBalance") - log.info(s"Balance before off-chain spending: $confirmedBalance") - log.info(s"Total with unconfirmed balance before spending: $totalBalance") - confirmedBalance - } - - val balanceToReturn = randomLong(balanceAmount(boxesToSpend)) - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn) - wallet.scanOffchain(spendingTx) - - eventually { - val confirmedAfterSpending = getConfirmedBalances.walletBalance - val totalAfterSpending = getBalancesWithUnconfirmed.walletBalance - - confirmedAfterSpending shouldBe confirmedBalance - totalAfterSpending shouldBe balanceToReturn - - log.info(s"After spending before rollback: $confirmedAfterSpending") - log.info(s"Total with unconfirmed balance after spending before rollback: $totalAfterSpending") - } - - wallet.rollback(initialState.version) - eventually { - val balanceAfterRollback = getConfirmedBalances.walletBalance - val totalAfterRollback = getBalancesWithUnconfirmed.walletBalance - - log.info(s"Balance after rollback: $balanceAfterRollback") - log.info(s"Total with unconfirmed balance after rollback: $totalAfterRollback") - - balanceAfterRollback shouldBe initialBalance - totalAfterRollback shouldBe balanceToReturn - } - } - } - - property("on-chain rollback") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey) - val boxesToSpend = boxesAvailable(genesisBlock, pubKey) - applyBlock(genesisBlock) shouldBe 'success - val initialState = getCurrentState - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - val (initialBalance, creationTx, initialAssets, balanceToSpend) = - eventually { - val initialBalance = getConfirmedBalances.walletBalance - val balanceToSpend = randomLong(balanceAmount(boxesToSpend)) - val creationTx = makeTx(boxesToSpend, emptyProverResult, balanceToSpend, pubKey, randomNewAsset) - val initialAssets = assetAmount(boxesAvailable(creationTx, pubKey)) - initialAssets should not be empty - log.info(s"Initial balance: $initialBalance") - log.info(s"Initial assets: $initialAssets") - (initialBalance, creationTx, initialAssets, balanceToSpend) - } - - val block = makeNextBlock(getUtxoState, Seq(creationTx)) - wallet.scanPersistent(block) - eventually { - val historyHeight = getHistory.headersHeight - - val confirmedBeforeRollback: WalletDigest = getConfirmedBalances - val totalBeforeRollback = getBalancesWithUnconfirmed - log.info(s"History height: $historyHeight") - log.info(s"Confirmed balance: $confirmedBeforeRollback") - log.info(s"Total with unconfirmed balance: $totalBeforeRollback") - - confirmedBeforeRollback.walletBalance shouldBe balanceToSpend - confirmedBeforeRollback.walletAssetBalances shouldBe initialAssets - totalBeforeRollback shouldBe confirmedBeforeRollback - } - wallet.rollback(initialState.version) - eventually { - val confirmedAfterRollback = getConfirmedBalances - val totalAfterRollback = getBalancesWithUnconfirmed - - log.info(s"Balance after rollback: $confirmedAfterRollback") - log.info(s"Total with unconfirmed balance after rollback: $totalAfterRollback") - - confirmedAfterRollback.walletBalance shouldBe initialBalance - confirmedAfterRollback.walletAssetBalances shouldBe empty - totalAfterRollback.walletBalance shouldBe balanceToSpend - totalAfterRollback.walletAssetBalances shouldBe initialAssets - } - } - } - - property("on-chain spending rollback") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey, randomNewAsset) - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - val sumBalance = balanceAmount(boxesToSpend) - val sumAssets = assetAmount(boxesToSpend) - sumAssets should not be empty - - applyBlock(genesisBlock) shouldBe 'success - val initialState = getCurrentState - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.second, 100.millis) - val (block, initialSnapshot) = - eventually { - val initialSnapshot = getConfirmedBalances - log.info(s"Initial balance: $initialSnapshot") - val spendingTx = makeSpendingTx(boxesToSpend, address) - val block = makeNextBlock(getUtxoState, Seq(spendingTx)) - initialSnapshot.walletBalance shouldBe sumBalance - initialSnapshot.walletAssetBalances shouldBe sumAssets - (block, initialSnapshot) - } - wallet.scanPersistent(block) - - val confirmedBeforeRollback = - eventually { - val historyHeight = getHistory.headersHeight - - val confirmedBeforeRollback = getConfirmedBalances - val totalBeforeRollback = getBalancesWithUnconfirmed - - log.info(s"Balance to spend: $sumBalance") - log.info(s"History height: $historyHeight") - log.info(s"Confirmed balance: $confirmedBeforeRollback") - log.info(s"Total with unconfirmed balance: $totalBeforeRollback") - - confirmedBeforeRollback.walletBalance shouldBe 0L - confirmedBeforeRollback.walletAssetBalances shouldBe empty - totalBeforeRollback shouldBe confirmedBeforeRollback - confirmedBeforeRollback - } - - wallet.rollback(initialState.version) - eventually { - val confirmedAfterRollback = getConfirmedBalances - val totalAfterRollback = getBalancesWithUnconfirmed - log.info(s"Balance after rollback: $confirmedAfterRollback") - log.info(s"Total with unconfirmed balance after rollback: $totalAfterRollback") - - confirmedAfterRollback shouldBe initialSnapshot - totalAfterRollback.walletBalance shouldBe confirmedBeforeRollback.walletBalance - totalAfterRollback.walletAssetBalances shouldBe confirmedBeforeRollback.walletAssetBalances - } - } - } - - property("on-chain spending with return rollback") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey, randomNewAsset) - val boxesToSpend = boxesAvailable(genesisBlock, address.pubkey) - val sumBalance = balanceAmount(boxesToSpend) - - applyBlock(genesisBlock) shouldBe 'success - val initialState = getCurrentState - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - val (block, initialSnapshot, asset1Map, balanceToReturn) = - eventually { - val initialSnapshot = getConfirmedBalances - - val balanceToReturn = randomLong(sumBalance) - val sumAsset1 = assetsByTokenId(boxesToSpend).toSeq - sumAsset1 should not be empty - - val asset1Map = toAssetMap(sumAsset1) - val assetToReturn = sumAsset1.map { case (tokenId, tokenValue) => (tokenId, randomLong(tokenValue)) } - val assetsForSpending = randomNewAsset ++ assetToReturn - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsForSpending) - val block = makeNextBlock(getUtxoState, Seq(spendingTx)) - log.info(s"Initial balance: $initialSnapshot") - log.info(s"Balance to spend: $sumBalance") - log.info(s"Balance to return $balanceToReturn") - initialSnapshot.walletBalance shouldBe sumBalance - initialSnapshot.walletAssetBalances.toMap shouldBe asset1Map - (block, initialSnapshot, asset1Map, balanceToReturn) - } - wallet.scanPersistent(block) - - val totalBeforeRollback = - eventually { - val historyHeight = getHistory.headersHeight - val confirmedBeforeRollback = getConfirmedBalances - val totalBeforeRollback = getBalancesWithUnconfirmed - log.info(s"History height: $historyHeight") - log.info(s"Confirmed balance: $confirmedBeforeRollback") - log.info(s"Total with unconfirmed balance: $totalBeforeRollback") - confirmedBeforeRollback.walletBalance should be > 0L - confirmedBeforeRollback.walletBalance shouldBe balanceToReturn - confirmedBeforeRollback.walletAssetBalances should have size 2 - totalBeforeRollback.walletBalance shouldBe balanceToReturn - totalBeforeRollback.walletAssetBalances.toMap shouldBe confirmedBeforeRollback.walletAssetBalances.toMap - totalBeforeRollback - } - wallet.rollback(initialState.version) - - eventually { - val confirmedAfterRollback = getConfirmedBalances - val totalAfterRollback = getBalancesWithUnconfirmed - log.info(s"Balance after rollback: $confirmedAfterRollback") - log.info(s"Total with unconfirmed balance after rollback: $totalAfterRollback") - confirmedAfterRollback shouldBe initialSnapshot - confirmedAfterRollback.walletAssetBalances.toMap shouldBe asset1Map - totalAfterRollback.walletBalance shouldBe balanceToReturn - totalAfterRollback.walletAssetBalances shouldBe totalBeforeRollback.walletAssetBalances - } - } - } - - property("on-chain spent box to off-chain box rollback") { - withFixture { implicit w => - val address = getPublicKeys.head - val genesisBlock = makeGenesisBlock(address.pubkey) - val initialBoxes = boxesAvailable(genesisBlock, address.pubkey) - applyBlock(genesisBlock) shouldBe 'success - val initialState = getCurrentState - val initialBalance = balanceAmount(initialBoxes) - - val balancePicked = randomLong(initialBalance) - val creationTx = makeTx(initialBoxes, emptyProverResult, balancePicked, address.pubkey, randomNewAsset) - val boxesToSpend = boxesAvailable(creationTx, address.pubkey) - val balanceToSpend = balanceAmount(boxesToSpend) - - log.info(s"Initial balance: $initialBalance") - log.info(s"Balance to spend: $balanceToSpend") - balanceToSpend shouldBe balancePicked - - val balanceToReturn = randomLong(balanceToSpend) - val sumAsset1 = assetsByTokenId(boxesToSpend).toSeq - sumAsset1 should not be empty - - val assetToReturn = sumAsset1.map { case (tokenId, tokenValue) => (tokenId, randomLong(tokenValue)) } - val assetsForSpending = randomNewAsset ++ assetToReturn - val spendingTx = makeSpendingTx(boxesToSpend, address, balanceToReturn, assetsForSpending) - val block = makeNextBlock(getUtxoState, Seq(creationTx, spendingTx)) - wallet.scanPersistent(block) - - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - val totalBeforeRollback = - eventually { - val historyHeight = getHistory.headersHeight - - val confirmedBeforeRollback = getConfirmedBalances - val totalBeforeRollback = getBalancesWithUnconfirmed - log.info(s"History height: $historyHeight") - log.info(s"Confirmed balance: $confirmedBeforeRollback") - log.info(s"Total with unconfirmed balance: $totalBeforeRollback") - - confirmedBeforeRollback.walletBalance shouldBe balanceToReturn - confirmedBeforeRollback.walletAssetBalances should have size 2 - - totalBeforeRollback.walletBalance shouldBe confirmedBeforeRollback.walletBalance - totalBeforeRollback.walletAssetBalances.toMap shouldBe confirmedBeforeRollback.walletAssetBalances.toMap - totalBeforeRollback - } - wallet.rollback(initialState.version) - - eventually { - val confirmedAfterRollback = getConfirmedBalances - val totalAfterRollback = getBalancesWithUnconfirmed - - log.info(s"Balance after rollback: $confirmedAfterRollback") - log.info(s"Total with unconfirmed balance after rollback: $totalAfterRollback") - - confirmedAfterRollback.walletBalance shouldBe initialBalance - totalAfterRollback.walletBalance shouldBe balanceToReturn - totalAfterRollback.walletAssetBalances shouldBe totalBeforeRollback.walletAssetBalances - } - } - } - - property("single-input transaction generation") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance, assetToSpend, Map.empty) - - val tx1 = await(wallet.generateTransaction(Seq(req1))).get - tx1.outputs.size shouldBe 1 - tx1.outputs.head.value shouldBe confirmedBalance - toAssetMap(tx1.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - - //change == 1: - val assetToSpend2 = assetToSpend.map { case (tokenId, tokenValue) => (tokenId, tokenValue - 1) } - val assetToReturn = assetToSpend.map { case (tokenId, _) => (tokenId, 1L) } - val req2 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance - MinBoxValue, assetToSpend2, Map.empty) - - val tx2 = await(wallet.generateTransaction(Seq(req2))).get - tx2.outputs.size shouldBe 2 - tx2.outputs.head.value shouldBe confirmedBalance - MinBoxValue - toAssetMap(tx2.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend2) - tx2.outputs(1).value shouldBe MinBoxValue - toAssetMap(tx2.outputs(1).additionalTokens.toArray) shouldBe toAssetMap(assetToReturn) - } - } - } - - property("generate unsigned transaction + sign (single input)") { - withFixture { implicit w => - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(Constants.TrueLeaf), confirmedBalance, assetToSpend, Map.empty) - - val utx = await(wallet.generateUnsignedTransaction(Seq(req1))).get - utx.outputs.size shouldBe 1 - utx.outputs.head.value shouldBe confirmedBalance - toAssetMap(utx.outputs.head.additionalTokens.toArray) shouldBe toAssetMap(assetToSpend) - - val tx = await(wallet.signTransaction(utx, Seq.empty, TransactionHintsBag.empty, None, None)).get - tx.id shouldBe utx.id // signing preserves transaction id - } - } - } - - property("co-signing (external secrets) - 2-out-of-2") { - withFixture { implicit w => - - val secret1 = DLogProverInput.random() - val es1 = ExternalSecret(PrimitiveSecretKey(secret1)) - - val secret2 = DLogProverInput.random() - val es2 = ExternalSecret(PrimitiveSecretKey(secret2)) - - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val req1 = PaymentRequest(Pay2SAddress(CAND(Seq(secret1.publicImage, secret2.publicImage))), confirmedBalance, assetToSpend, Map.empty) - - val tx = await(wallet.generateTransaction(Seq(req1))).get - - val in = tx.outputs.head - - val utx = new UnsignedErgoTransaction(IndexedSeq(new UnsignedInput(in.id)), IndexedSeq.empty, IndexedSeq(in.toCandidate)) - - val hints1 = await(wallet.generateCommitmentsFor(utx, Some(Seq(es1)), Some(Seq(in)), None)).response.get - - val txSigned = await(wallet.signTransaction(utx, Seq(es2), hints1, Some(Seq(in)), None)).get - - txSigned.statelessValidity().isSuccess shouldBe true - } - } - } - - property("co-signing (external secrets) - 2-out-of-3") { - withFixture { implicit w => - val secret1 = DLogProverInput.random() - val es1 = ExternalSecret(PrimitiveSecretKey(secret1)) - - val secret2 = DLogProverInput.random() - val es2 = ExternalSecret(PrimitiveSecretKey(secret2)) - - val secret3 = DLogProverInput.random() - - val pubKey = getPublicKeys.head.pubkey - val genesisBlock = makeGenesisBlock(pubKey, randomNewAsset) - applyBlock(genesisBlock) shouldBe 'success - implicit val patienceConfig: PatienceConfig = PatienceConfig(5.seconds, 100.millis) - eventually { - val confirmedBalance = getConfirmedBalances.walletBalance - - //pay out all the wallet balance: - val assetToSpend = assetsByTokenId(boxesAvailable(genesisBlock, pubKey)).toSeq - assetToSpend should not be empty - val addr = Pay2SAddress(CTHRESHOLD(2, Seq(secret1.publicImage, secret2.publicImage, secret3.publicImage))) - val req1 = PaymentRequest(addr, confirmedBalance, assetToSpend, Map.empty) - - val tx = await(wallet.generateTransaction(Seq(req1))).get - - val in = tx.outputs.head - - // secret1 and secret2 are signing - val utx = new UnsignedErgoTransaction(IndexedSeq(new UnsignedInput(in.id)), IndexedSeq.empty, IndexedSeq(in.toCandidate)) - - val cmts1 = await(wallet.generateCommitmentsFor(utx, Some(Seq(es1)), Some(Seq(in)), None)).response.get - - val pubCmts1 = TransactionHintsBag(cmts1.publicHints) - - val ptx = await(wallet.signTransaction(utx, Seq(es2), pubCmts1, Some(Seq(in)), None)).get - - val eh = wallet.extractHints(ptx, Seq(secret1.publicImage, secret2.publicImage), Seq(secret3.publicImage), Some(Seq(in)), None) - val hintsExtracted = await(eh).transactionHintsBag - - val hints = hintsExtracted.addHintsForInput(0, cmts1.allHintsForInput(0)) - - val txSigned = await(wallet.signTransaction(utx, Seq(es1), hints, Some(Seq(in)), None)).get - txSigned.statelessValidity().isSuccess shouldBe true - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletProfileSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletProfileSpec.scala deleted file mode 100644 index caf1103277..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletProfileSpec.scala +++ /dev/null @@ -1,20 +0,0 @@ -package org.ergoplatform.nodeView.wallet - -import org.ergoplatform.utils.ErgoPropertyTest - -import scala.util.Try - -class WalletProfileSpec extends ErgoPropertyTest { - property("fromLabel getting profiles properly") { - WalletProfile.fromLabel("user").outputsFilterSize shouldBe WalletProfile.User.outputsFilterSize - WalletProfile.fromLabel("user").scriptsFilterSize shouldBe WalletProfile.User.scriptsFilterSize - - WalletProfile.fromLabel("exchange").scriptsFilterSize should not be WalletProfile.User.scriptsFilterSize - WalletProfile.fromLabel("exchange").outputsFilterSize shouldBe WalletProfile.Exchange.outputsFilterSize - WalletProfile.fromLabel("exchange").scriptsFilterSize shouldBe WalletProfile.Exchange.scriptsFilterSize - - Try(WalletProfile.fromLabel("appserver")).isFailure shouldBe true - WalletProfile.fromLabel("appServer").outputsFilterSize shouldBe WalletProfile.AppServer.outputsFilterSize - WalletProfile.fromLabel("appServer").scriptsFilterSize shouldBe WalletProfile.AppServer.scriptsFilterSize - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala deleted file mode 100644 index fb6d72e266..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletScanLogicSpec.scala +++ /dev/null @@ -1,282 +0,0 @@ -package org.ergoplatform.nodeView.wallet - -import org.ergoplatform.utils.{ErgoPropertyTest, WalletTestOps} -import WalletScanLogic.{extractWalletOutputs, scanBlockTransactions} -import org.ergoplatform.db.DBSpec -import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, Input} -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.wallet.persistence.{OffChainRegistry, WalletRegistry} -import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, ScanRequest, ScanWalletInteraction} -import org.ergoplatform.wallet.Constants -import org.ergoplatform.wallet.Constants.ScanId -import org.scalacheck.Gen -import sigmastate.Values.{ByteArrayConstant, ErgoTree, FalseLeaf, TrueLeaf} - -import scala.util.Random - -class WalletScanLogicSpec extends ErgoPropertyTest with DBSpec with WalletTestOps { - - private case class TrackedTransaction(tx: ErgoTransaction, - payments: List[ErgoTree], - paymentValues: List[Int], - appPayments: List[ErgoTree], - appPaymentValues: List[Int], - miningRewards: List[ErgoTree], - miningRewardValues: List[Int]) { - def scriptsCount: Int = payments.size + appPayments.size + miningRewards.size - - def valuesSum: Long = (paymentValues ++ appPaymentValues ++ miningRewardValues).sum - } - - private val prover = defaultProver - private val monetarySettings = initSettings.chainSettings.monetary.copy(minerRewardDelay = 720) - private val s = initSettings.copy(chainSettings = initSettings.chainSettings.copy(monetary = monetarySettings)) - - private val trueProp = org.ergoplatform.settings.Constants.TrueLeaf - private val scanningPredicate = EqualsScanningPredicate(ErgoBox.ScriptRegId, ByteArrayConstant(trueProp.bytes)) - private val appReq = ScanRequest("True detector", scanningPredicate, Some(ScanWalletInteraction.Off), None) - private val scanId: ScanId = ScanId @@ 50.toShort - - private val pubkeys = prover.hdPubKeys - private val miningScripts = WalletCache.miningScripts(pubkeys, s) - - private def paymentsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.oneOf(pubkeys.map(_.key.toSigmaProp: ErgoTree))) - - private def miningRewardsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.oneOf(miningScripts)) - - private def nonTrackablePaymentsGen: Gen[List[ErgoTree]] = Gen.nonEmptyListOf(Gen.const(FalseLeaf.toSigmaProp)) - - private def appPaymentsGen: Gen[List[ErgoTree]] = Gen.listOf(Gen.const(trueProp)) - - private def walletVarsGen: Gen[WalletVars] = { - for { - // To check that scanning works with locked wallet, we randomly choose whether the prover is set or not - proverSet <- Gen.oneOf(true, false) - } yield { - if (proverSet) { - WalletVars(Some(prover), Seq(appReq.toScan(scanId).get), None)(s) - } else { - val cache = WalletCache(pubkeys, s) - WalletVars(None, Seq(appReq.toScan(scanId).get), Some(cache))(s) - } - } - } - - private def trackedTransactionGen: Gen[TrackedTransaction] = { - for { - payments <- paymentsGen - appPayments <- appPaymentsGen - miningRewards <- miningRewardsGen - nonTrackablePayments <- nonTrackablePaymentsGen - } yield { - def valueGen(): Int = Random.nextInt(1000) + 100 - - val appPaymentValues = appPayments.map(_ => valueGen()) - val paymentValues = payments.map(_ => valueGen()) - val miningRewardValues = miningRewards.map(_ => valueGen()) - val nonTrackableValues = nonTrackablePayments.map(_ => valueGen()) - val outs = (payments ++ appPayments ++ miningRewards ++ nonTrackablePayments) - .zip(paymentValues ++ appPaymentValues ++ miningRewardValues ++ nonTrackableValues) - .map { case (script, vl) => new ErgoBoxCandidate(vl, script, creationHeight = 1) } - .toIndexedSeq - - val tx = new ErgoTransaction(fakeInputs, IndexedSeq.empty, outs) - - TrackedTransaction(tx, payments, paymentValues, appPayments, appPaymentValues, miningRewards, miningRewardValues) - } - } - - property("extractWalletOutputs properly extracts") { - val height = Random.nextInt(200) - 100 - val inclusionHeightOpt = if (height <= 0) None else Some(height) - - forAll(trackedTransactionGen, walletVarsGen) { case (trackedTransaction, walletVars) => - val foundBoxes = extractWalletOutputs(trackedTransaction.tx, inclusionHeightOpt, walletVars, None) - foundBoxes.length shouldBe trackedTransaction.scriptsCount - foundBoxes.map(_.inclusionHeightOpt).forall(_ == inclusionHeightOpt) shouldBe true - foundBoxes.map(_.value).sum shouldBe trackedTransaction.valuesSum - foundBoxes.forall(tb => if (trackedTransaction.payments.contains(tb.box.ergoTree)) { - tb.scans == Set(Constants.PaymentsScanId) - } else if (trackedTransaction.miningRewards.contains(tb.box.ergoTree)) { - tb.scans == Set(Constants.MiningScanId) - } else { - tb.scans == Set(scanId) - }) shouldBe true - } - } - - property("extractWalletOutputs filters out boxes with dust") { - val height = Random.nextInt(200) - 100 - val inclusionHeightOpt = if (height <= 0) None else Some(height) - forAll(trackedTransactionGen, walletVarsGen) { case (trackedTransaction, walletVars) => - val highDustLimit = Some(Long.MaxValue) - val foundBoxes1 = extractWalletOutputs(trackedTransaction.tx, inclusionHeightOpt, walletVars, highDustLimit) - foundBoxes1 shouldBe empty - val lowDustLimit = Some(1L) - val foundBoxes2 = extractWalletOutputs(trackedTransaction.tx, inclusionHeightOpt, walletVars, lowDustLimit) - foundBoxes2.forall(_.value > 1) shouldBe true - } - } - - property("scanBlockTransactions") { - withVersionedStore(10) { store => - val walletVars = walletVarsGen.sample.get - val emptyReg = new WalletRegistry(store)(settings.walletSettings) - val emptyOff = OffChainRegistry.empty - val blockId = modIdGen.sample.get - - val height0 = 5 - //simplest case - we're scanning an empty block - val (r0, o0, f0) = - scanBlockTransactions(emptyReg, emptyOff, walletVars, height0, blockId, - Seq.empty, None, None, WalletProfile.User).get - val r0digest = r0.fetchDigest() - r0digest.walletBalance shouldBe 0 - r0digest.walletAssetBalances.size shouldBe 0 - r0digest.height shouldBe height0 - - val o0digest = o0.digest - o0digest.walletBalance shouldBe 0 - o0digest.walletAssetBalances.size shouldBe 0 - o0digest.height shouldBe height0 - - var registry = r0 - var off = o0 - - forAll(trackedTransactionGen) { trackedTransaction => - //applying one transaction creating boxes - val creatingTx = trackedTransaction.tx - val txs = Seq(creatingTx) - val height1 = 5 - - val regDigestBefore = registry.fetchDigest().walletBalance - val offDigestBefore = off.digest.walletBalance - - val (r1, o1, f1) = - scanBlockTransactions(registry, off, walletVars, height1, blockId, - txs, Some(f0), None, WalletProfile.User).get - val r1digest = r1.fetchDigest() - r1digest.walletBalance shouldBe (regDigestBefore + trackedTransaction.paymentValues.sum) - r1digest.walletAssetBalances.size shouldBe 0 - r1digest.height shouldBe height1 - - val o1digest = o1.digest - o1digest.walletBalance shouldBe (offDigestBefore + trackedTransaction.paymentValues.sum) - o1digest.walletAssetBalances.size shouldBe 0 - o1digest.height shouldBe height1 - - registry = r1 - off = o1 - - //applying a transaction spending outputs of previous transaction and creating new one with the same outputs - val tx = trackedTransaction.tx - val inputs = tx.outputs.map(_.id).map(id => Input(id, emptyProverResult)) - val spendingTx = ErgoTransaction(inputs, IndexedSeq.empty, tx.outputCandidates) - - val (r2, o2, f2) = - scanBlockTransactions(registry, off, walletVars, height1 + 1, blockId, - Seq(spendingTx), Some(f1), None, WalletProfile.User).get - - val r2digest = r2.fetchDigest() - r2digest.walletBalance shouldBe (regDigestBefore + trackedTransaction.paymentValues.sum) - r2digest.walletAssetBalances.size shouldBe 0 - r2digest.height shouldBe height1 + 1 - - val o2digest = o2.digest - o2digest.walletBalance shouldBe (offDigestBefore + trackedTransaction.paymentValues.sum) - o2digest.walletAssetBalances.size shouldBe 0 - o2digest.height shouldBe height1 + 1 - - registry = r2 - off = o2 - - //applying a transaction spending outputs of the previous transaction - val inputs2 = spendingTx.outputs.map(_.id).map(id => Input(id, emptyProverResult)) - val outputs2 = IndexedSeq(new ErgoBoxCandidate(spendingTx.outputs.map(_.value).sum, FalseLeaf.toSigmaProp, height1)) - val spendingTx2 = new ErgoTransaction(inputs2, IndexedSeq.empty, outputs2) - - val (r3, o3, f3) = - scanBlockTransactions(registry, off, walletVars, height1 + 2, blockId, - Seq(spendingTx2), Some(f2), None, WalletProfile.User).get - - val r3digest = r3.fetchDigest() - r3digest.walletBalance shouldBe regDigestBefore - r3digest.walletAssetBalances.size shouldBe 0 - r3digest.height shouldBe height1 + 2 - - val o3digest = o3.digest - o3digest.walletBalance shouldBe offDigestBefore - o3digest.walletAssetBalances.size shouldBe 0 - o3digest.height shouldBe height1 + 2 - - registry = r3 - off = o3 - - //applying all the three previous transactions - val threeTxs = Seq(creatingTx, spendingTx, spendingTx2) - - val (r4, o4, _) = - scanBlockTransactions(registry, off, walletVars, height1 + 3, blockId, - threeTxs, Some(f3), None, WalletProfile.User).get - - val r4digest = r4.fetchDigest() - r4digest.walletBalance shouldBe regDigestBefore - r4digest.walletAssetBalances.size shouldBe 0 - r4digest.height shouldBe height1 + 3 - r4.walletUnspentBoxes() shouldBe Seq.empty - - val o4digest = o4.digest - o4digest.walletBalance shouldBe offDigestBefore - o4digest.walletAssetBalances.size shouldBe 0 - o4digest.height shouldBe height1 + 3 - - registry = r4 - off = o4 - } - } - } - - property("external scan prioritized over payments one if walletInteraction = off, otherwise shared") { - val intFlagGen = Gen.oneOf(ScanWalletInteraction.Off, ScanWalletInteraction.Shared, ScanWalletInteraction.Forced) - forAll(intFlagGen) { intFlag => - val pk = pubkeys.head.key.toSigmaProp: ErgoTree - val outs = IndexedSeq(new ErgoBoxCandidate(1000, pk, creationHeight = 1)) - val tx = new ErgoTransaction(fakeInputs, IndexedSeq.empty, outs) - - val cache = WalletCache(pubkeys, s) - val paymentPredicate = EqualsScanningPredicate(ErgoBox.ScriptRegId, ByteArrayConstant(pk.bytes)) - val paymentScanReq = ScanRequest("Payment scan", paymentPredicate, Some(intFlag), Some(true)) - val walletVars = WalletVars(None, Seq(paymentScanReq.toScan(scanId).get), Some(cache))(s) - - val boxes = extractWalletOutputs(tx, Some(1), walletVars, None) - - if (intFlag == ScanWalletInteraction.Shared || intFlag == ScanWalletInteraction.Forced) { - boxes.size shouldBe 1 - boxes.head.scans.size shouldBe 2 - boxes.head.scans shouldBe Set(scanId, Constants.PaymentsScanId) - } else { - boxes.size shouldBe 1 - boxes.head.scans.size shouldBe 1 - boxes.head.scans.head shouldBe scanId - } - } - } - - property("scan with forced flag is sharing boxes with the p2k-wallet") { - val trueProp = TrueLeaf.toSigmaProp.treeWithSegregation: ErgoTree - val outs = IndexedSeq(new ErgoBoxCandidate(1000, trueProp, creationHeight = 1)) - val tx = new ErgoTransaction(fakeInputs, IndexedSeq.empty, outs) - - val cache = WalletCache(pubkeys, s) - val paymentPredicate = EqualsScanningPredicate(ErgoBox.ScriptRegId, ByteArrayConstant(trueProp.bytes)) - val paymentScanReq = ScanRequest("Payment scan", paymentPredicate, Some(ScanWalletInteraction.Forced), Some(false)) - val walletVars = WalletVars(None, Seq(paymentScanReq.toScan(scanId).get), Some(cache))(s) - - val boxes = extractWalletOutputs(tx, Some(1), walletVars, None) - - boxes.size shouldBe 1 - boxes.head.scans.size shouldBe 2 - boxes.head.scans shouldBe Set(scanId, Constants.PaymentsScanId) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletVarsSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletVarsSpec.scala deleted file mode 100644 index 6df68147b6..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/WalletVarsSpec.scala +++ /dev/null @@ -1,19 +0,0 @@ -package org.ergoplatform.nodeView.wallet - -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.wallet.interpreter.ErgoProvingInterpreter - -class WalletVarsSpec extends ErgoPropertyTest { - - property(".withProver init") { - val prover = ErgoProvingInterpreter(defaultRootSecret, parameters) - val walletVars = WalletVars(None, Seq.empty, None) - val wp = walletVars.withProver(prover) - - wp.trackedPubKeys.length shouldBe 1 - wp.trackedBytes.length shouldBe 1 - - defaultRootSecret.publicKey shouldBe wp.trackedPubKeys.head - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala deleted file mode 100644 index 886fbf38ce..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/OffChainRegistrySpec.scala +++ /dev/null @@ -1,92 +0,0 @@ -package org.ergoplatform.nodeView.wallet.persistence - -import org.ergoplatform.ErgoBox -import org.ergoplatform.nodeView.wallet.IdUtils.{EncodedBoxId, encodedBoxId} -import org.ergoplatform.nodeView.wallet.scanning.{EqualsScanningPredicate, Scan, ScanWalletInteraction} -import org.ergoplatform.utils.WalletTestOps -import org.ergoplatform.utils.generators.WalletGenerators -import org.ergoplatform.wallet.Constants -import org.scalacheck.Gen -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import sigmastate.Values.ByteArrayConstant - -import scala.collection.immutable.TreeSet -import scala.util.Random - - -class OffChainRegistrySpec - extends AnyFlatSpec - with Matchers - with ScalaCheckPropertyChecks - with WalletGenerators - with WalletTestOps { - - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 5, sizeRange = 10) - - //registry.updateOnTransaction is called when offchain transaction comes - it should "calculate indexes correctly on offchain transaction" in { - forAll(Gen.listOf(trackedBoxGen)) { boxes => - //apply transaction outputs to empty offchain registry - var registry = OffChainRegistry.empty.updateOnTransaction(boxes, Seq.empty, Seq.empty) - val balance = balanceAmount(boxes.map(_.box)) - val assetsBalance = assetAmount(boxes.map(_.box)) - registry.digest.walletBalance shouldEqual balance - registry.digest.walletAssetBalances.toMap shouldEqual assetsBalance.toMap - - //spend all the outputs - registry = registry.updateOnTransaction(Seq.empty, boxes.map(EncodedBoxId @@@ _.boxId), Seq.empty) - registry.digest.walletBalance shouldEqual 0 - registry.digest.walletAssetBalances shouldEqual Seq.empty - - - //check remove-offchain flag - boxes.filter(_.scans.size > 1).flatMap(_.scans).find(_ != Constants.PaymentsScanId).map { scanId => - val trueProp = org.ergoplatform.settings.Constants.TrueLeaf - val p = EqualsScanningPredicate(ErgoBox.R1, ByteArrayConstant(trueProp.bytes)) - val scan = Scan(scanId, "_", p, ScanWalletInteraction.Off, removeOffchain = false) - val filtered = boxes.filter(tb => tb.scans.contains(scanId)) - - val fbalance = balanceAmount(filtered.map(_.box)) - val fassetsBalance = assetAmount(filtered.map(_.box)) - - registry = registry.updateOnTransaction(filtered, Seq.empty, Seq.empty) - registry.digest.walletBalance shouldEqual fbalance - registry.digest.walletAssetBalances.toMap shouldEqual fassetsBalance.toMap - - registry = registry.updateOnTransaction(Seq.empty, filtered.map(EncodedBoxId @@@ _.boxId), Seq(scan)) - registry.digest.walletBalance shouldEqual fbalance - registry.digest.walletAssetBalances.toMap shouldEqual fassetsBalance.toMap - - val scan2 = Scan(scanId, "_", p, ScanWalletInteraction.Off, removeOffchain = true) - registry = registry.updateOnTransaction(Seq.empty, filtered.map(EncodedBoxId @@@ _.boxId), Seq(scan2)) - registry.digest.walletBalance shouldEqual 0 - registry.digest.walletAssetBalances shouldEqual Seq.empty - } - } - } - - //registry.updateOnTransaction is called when a block comes - it should "calculate indexes correctly on a block" in { - forAll(Gen.listOf(trackedBoxGen)) { boxes => - val height = Random.nextInt(500) + 1 - - //apply block to empty registry - val registry = OffChainRegistry.empty.updateOnBlock(height, boxes, boxes.map(tb => encodedBoxId(tb.box.id)).to[TreeSet]) - val balance = balanceAmount(boxes.map(_.box)) - val assetsBalance = assetAmount(boxes.map(_.box)) - registry.height shouldEqual height - registry.digest.walletBalance shouldEqual balance - registry.digest.walletAssetBalances.toMap shouldEqual assetsBalance.toMap - - //a block coming is not making any offchain box on-chain - val registry2 = OffChainRegistry.empty.updateOnBlock(height, boxes, TreeSet.empty) - registry2.height shouldEqual height - registry2.digest.walletBalance shouldEqual balance - registry2.digest.walletAssetBalances.toMap shouldEqual assetsBalance.toMap - } - } - - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala deleted file mode 100644 index 1dad6a9df8..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistryBenchmark.scala +++ /dev/null @@ -1,86 +0,0 @@ -package org.ergoplatform.nodeView.wallet.persistence - -import org.ergoplatform.ErgoBox.{AdditionalRegisters, TokenId} -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.wallet.WalletScanLogic.ScanResults -import org.ergoplatform.nodeView.wallet.{WalletTransaction, WalletVars} -import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} -import org.ergoplatform.utils.ErgoTestConstants -import org.ergoplatform.wallet.Constants -import org.ergoplatform.wallet.boxes.TrackedBox -import org.ergoplatform.wallet.interpreter.ErgoProvingInterpreter -import org.ergoplatform.{ErgoAddressEncoder, ErgoBox, Input} -import scorex.util.ModifierId -import scorex.util.encode.Base16 -import sigmastate.Values.ErgoTree -import sigmastate.interpreter.{ContextExtension, ProverResult} - -import scala.collection.compat.immutable.ArraySeq - -object WalletRegistryBenchmark extends App with ErgoTestConstants { - - def createBox(value: Long, - ergoTree: ErgoTree, - creationHeight: Int, - additionalTokens: Seq[(TokenId, Long)] = Nil, - additionalRegisters: AdditionalRegisters = Map.empty, - transactionId: ModifierId = ErgoBox.allZerosModifierId, - boxIndex: Short = 0): ErgoBox = { - import sigmastate.eval._ - new ErgoBox(value, ergoTree, - CostingSigmaDslBuilder.Colls.fromArray(additionalTokens.toArray[(TokenId, Long)]), - additionalRegisters, - transactionId, boxIndex, creationHeight) - } - - implicit val enc = new ErgoAddressEncoder(ErgoAddressEncoder.MainnetNetworkPrefix) - - val registry = WalletRegistry(settings).get - val storage = WalletStorage.readOrCreate(settings) - - val rootSecret = ExtendedSecretKey.deriveMasterKey(Array.fill(32)(0: Byte), usePre1627KeyDerivation = false) - - val derivedSecrets = (1 to 15000).map { i => - val k = rootSecret.derive(DerivationPath.fromEncoded(s"m/44'/429'/0'/0/$i").get) - storage.addPublicKey(k.publicKey).get - k - } - - val prover = ErgoProvingInterpreter(rootSecret +: derivedSecrets, parameters) - val walletVars = WalletVars.apply(storage, settings).withProver(prover) - - val boxes = walletVars.proverOpt.get.hdPubKeys.map { pk => - createBox(1000000000, pk.key, 1) - }.map { box => - TrackedBox(box, 2, Set(Constants.PaymentsScanId)) - } - - val scanResults0 = ScanResults(boxes, ArraySeq.empty, ArraySeq.empty) - registry.updateOnBlock(scanResults0, ModifierId @@ Base16.encode(Array.fill(32)(0: Byte)), 1).get - println("keys: " + walletVars.proverOpt.get.secretKeys.size) - - val bts0 = System.currentTimeMillis() - val boxesRead = registry.unspentBoxes(Constants.PaymentsScanId) - val bts = System.currentTimeMillis() - println("boxes read: " + boxesRead.size) - println("boxes read time: " + (bts - bts0) + " ms") - - val stateContext = storage.readStateContext(parameters) - - val txs = boxes.map { tb => - val bx = tb.box - val input = new Input(bx.id, ProverResult(Array.fill(64)(0: Byte), ContextExtension.empty)) - val tx = ErgoTransaction(IndexedSeq(input), IndexedSeq(bx.toCandidate)) - WalletTransaction(tx, 2, Seq(Constants.PaymentsScanId)) - } - - val scanResults1 = ScanResults(ArraySeq.empty, ArraySeq.empty, txs) - registry.updateOnBlock(scanResults1, ModifierId @@ Base16.encode(Array.fill(32)(1: Byte)), 2).get - - val tts0 = System.currentTimeMillis() - val txsRead = registry.allWalletTxs() - val tts = System.currentTimeMillis() - println("txs read: " + txsRead.size) - println("txs read time: " + (tts - tts0) + " ms") - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala deleted file mode 100644 index 6b5dfb4977..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletRegistrySpec.scala +++ /dev/null @@ -1,366 +0,0 @@ -package org.ergoplatform.nodeView.wallet.persistence - -import com.google.common.primitives.{Ints, Shorts} -import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} -import org.ergoplatform.db.DBSpec -import org.ergoplatform.nodeView.wallet.WalletScanLogic.{ScanResults, SpentInputData} -import org.ergoplatform.utils.generators.WalletGenerators -import org.ergoplatform.wallet.boxes.TrackedBox -import org.scalacheck.Gen -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.core.VersionTag -import scorex.util.encode.Base16 - -import scala.collection.compat.immutable.ArraySeq -import scala.util.Success - -class WalletRegistrySpec - extends AnyFlatSpec - with Matchers - with DBSpec - with ScalaCheckPropertyChecks - with WalletGenerators { - - implicit override val generatorDrivenConfig = PropertyCheckConfiguration(minSuccessful = 4, sizeRange = 10) - - private val emptyBag = KeyValuePairsBag.empty - private val walletBoxStatus = Set(PaymentsScanId) - - private val ws = settings.walletSettings - - it should "read unspent wallet boxes" in { - forAll(trackedBoxGen) { box => - withVersionedStore(10) { store => - val unspentBox = box.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = walletBoxStatus) - WalletRegistry.putBox(emptyBag, unspentBox).transact(store).get - - val registry = new WalletRegistry(store)(settings.walletSettings) - registry.walletUnspentBoxes() shouldBe Seq(unspentBox) - - //put app box - val appId = ScanId @@ (PaymentsScanId + 1).toShort - val unspentAppBox = box.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = Set(appId)) - WalletRegistry.putBox(emptyBag, unspentAppBox).transact(store).get - registry.walletUnspentBoxes() shouldBe Seq(unspentBox) - registry.allUnspentBoxes() shouldBe Seq(unspentBox, unspentAppBox) - } - } - } - - it should "read spent wallet boxes" in { - forAll(trackedBoxGen, modifierIdGen) { case (box, txId) => - withVersionedStore(10) { store => - val spentBox = box.copy(spendingHeightOpt = Some(10000), spendingTxIdOpt = Some(txId), scans = walletBoxStatus) - WalletRegistry.putBox(emptyBag, spentBox).transact(store).get - val registry = new WalletRegistry(store)(settings.walletSettings) - registry.walletSpentBoxes() shouldBe Seq(spentBox) - } - } - } - - it should "read confirmed wallet boxes" in { - forAll(trackedBoxGen, modifierIdGen) { case (box, txId) => - withVersionedStore(10) { store => - val unspentBox = box.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = walletBoxStatus) - val spentBox = box.copy(spendingHeightOpt = Some(10000), spendingTxIdOpt = Some(txId), scans = walletBoxStatus) - WalletRegistry.putBoxes(emptyBag, Seq(unspentBox, spentBox)).transact(store).get - val registry = new WalletRegistry(store)(settings.walletSettings) - registry.walletSpentBoxes() shouldBe Seq(spentBox) - registry.walletUnspentBoxes() shouldBe Seq(unspentBox) - registry.walletConfirmedBoxes() shouldBe Seq(unspentBox, spentBox) - } - } - } - - it should "read wallet transactions" in { - forAll(walletTransactionGen) { wtx => - withVersionedStore(10) { store => - WalletRegistry.putTx(emptyBag, wtx).transact(store).get - val registry = new WalletRegistry(store)(settings.walletSettings) - - registry.allWalletTxs() shouldBe Seq(wtx) - } - } - } - - it should "update historical boxes when `keepSpentBoxes = true`" in { - val ws = settings.walletSettings.copy(keepSpentBoxes = true) - val spendingHeight = 0 - forAll(Gen.nonEmptyListOf(trackedBoxGen), modifierIdGen) { (boxes, txId) => - withVersionedStore(10) { store => - val unspentBoxes = boxes.map( - _.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = walletBoxStatus)) - val transitedBoxes = unspentBoxes.map( - _.copy(spendingHeightOpt = Some(spendingHeight), spendingTxIdOpt = Some(txId))) - - WalletRegistry.putBoxes(emptyBag, unspentBoxes).transact(store).get - val registry = new WalletRegistry(store)(ws) - registry.processSpentBoxes(emptyBag, unspentBoxes.map(txId -> _), spendingHeight).transact(store).get - registry.walletSpentBoxes().toList should contain theSameElementsAs transitedBoxes - } - } - } - - it should "updateOnBlock() in correct way - only outputs" in { - forAll(Gen.nonEmptyListOf(trackedBoxGen)) { boxes => - withVersionedStore(10) { store => - val registry = new WalletRegistry(store)(settings.walletSettings) - val blockId = modifierIdGen.sample.get - val unspentBoxes = boxes.map(bx => bx.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = walletBoxStatus)) - registry.updateOnBlock(ScanResults(unspentBoxes, ArraySeq.empty, ArraySeq.empty), blockId, 100).get - registry.walletUnspentBoxes().toList should contain theSameElementsAs unspentBoxes - } - } - } - - private def outputsSpentTest(keepSpent: Boolean): Unit = forAll(Gen.nonEmptyListOf(trackedBoxGen)) { boxes => - withVersionedStore(10) { store => - val fakeTxId = modifierIdGen.sample.get - val registry = new WalletRegistry(store)(settings.walletSettings.copy(keepSpentBoxes = keepSpent)) - val blockId = modifierIdGen.sample.get - val outs = boxes.map { bx => - bx.copy(spendingHeightOpt = None, spendingTxIdOpt = None, scans = walletBoxStatus) - } - val inputs = outs.map(tb => SpentInputData(fakeTxId, tb)) - registry.updateOnBlock(ScanResults(outs, inputs, ArraySeq.empty), blockId, 100).get - registry.walletUnspentBoxes() shouldBe Seq.empty - } - } - - it should "updateOnBlock() in correct way - outputs spent" in { - outputsSpentTest(keepSpent = false) - outputsSpentTest(keepSpent = true) - } - - it should "putBox/getBox/removeBox" in { - forAll(trackedBoxGen) { tb => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - WalletRegistry.putBox(emptyBag, tb).transact(store).get - reg.getBox(tb.box.id) shouldBe Some(tb) - reg.cache -= tb.boxId - WalletRegistry.removeBoxes(emptyBag, Seq(tb)).transact(store).get - reg.getBox(tb.box.id) shouldBe None - } - } - } - - it should "putBox/removeBox - 2 versions" in { - forAll(trackedBoxGen) { tb => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - val tb1 = tb.copy(spendingHeightOpt = None, spendingTxIdOpt = None) - val bag1 = WalletRegistry.putBox(emptyBag, tb1) - - val tb2 = tb.copy(spendingHeightOpt = Some(5000), spendingTxIdOpt = Some(modifierIdGen.sample.get)) - val bag2 = WalletRegistry.removeBox(bag1, tb1) - WalletRegistry.putBox(bag2, tb2).transact(store).get - reg.getBox(tb.box.id) shouldBe Some(tb2) - reg.walletUnspentBoxes() shouldBe Seq.empty - } - } - } - - it should "putBoxes/getBoxes/removeBoxes" in { - forAll(Gen.listOf(trackedBoxGen)) { tbs => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - WalletRegistry.putBoxes(emptyBag, tbs).transact(store).get - reg.getBoxes(tbs.map(_.box.id)) should contain theSameElementsAs tbs.map(Some.apply) - val updateFn = (tb: TrackedBox) => tb.copy(spendingHeightOpt = Some(0), - scans = Set(PaymentsScanId, ScanId @@ 2.toShort)) - val updatedBoxes = tbs.map(updateFn) - reg.getBoxes(tbs.map(_.box.id)) should contain theSameElementsAs updatedBoxes.map(Some.apply) - reg.cache --= tbs.map(_.boxId) - WalletRegistry.removeBoxes(emptyBag, tbs).transact(store).get - reg.getBoxes(tbs.map(_.box.id)).flatten shouldBe Seq() - } - } - } - - it should "putTx/getTx/getAllTxs/removeTxs" in { - forAll(walletTransactionGen) { wtx => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - WalletRegistry.putTx(emptyBag, wtx).transact(store).get - reg.getTx(wtx.id) shouldEqual Some(wtx) - reg.allWalletTxs() shouldEqual Seq(wtx) - WalletRegistry.removeTxs(emptyBag, Seq(wtx)).transact(store).get - reg.allWalletTxs() should not contain wtx - } - } - } - - it should "putTxs/getAllTxs" in { - forAll(Gen.listOf(walletTransactionGen)) { wtxs => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - WalletRegistry.putTxs(emptyBag, wtxs).transact(store).get - reg.allWalletTxs() should contain theSameElementsAs wtxs - } - } - } - - it should "putIndex/digest/updateIndex" in { - forAll(registrySummaryGen) { index => - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - - WalletRegistry.putDigest(emptyBag, index).transact(store).get - reg.fetchDigest() shouldBe index - val updatedIndex = index.copy(height = 0, walletBalance = 0) - reg.updateDigest(emptyBag)(_ => Success(updatedIndex)).get.transact(store).get - reg.fetchDigest() shouldBe updatedIndex - } - } - } - - it should "update scans correctly" in { - val appId1: ScanId = ScanId @@ 21.toShort - val appId2: ScanId = ScanId @@ 22.toShort - - forAll(trackedBoxGen) { tb0 => - withVersionedStore(10) { store => - val tb1 = tb0.copy(scans = Set(appId1, appId2), spendingHeightOpt = None, spendingTxIdOpt = None) - - val reg = new WalletRegistry(store)(ws) - WalletRegistry.putBox(emptyBag, tb1).transact(store).get - reg.getBox(tb1.box.id).get.scans shouldBe Set(appId1, appId2) - reg.unspentBoxes(appId1).length shouldBe 1 - reg.unspentBoxes(appId2).length shouldBe 1 - reg.updateScans(Set(appId1), tb1.box) - reg.getBox(tb1.box.id).get.scans shouldBe Set(appId1) - reg.unspentBoxes(appId1).length shouldBe 1 - reg.unspentBoxes(appId2).length shouldBe 0 - // limit should by applied - reg.unspentBoxes(appId1, limit = 1).length shouldBe 1 - reg.unspentBoxes(appId1, limit = 0).length shouldBe 0 - } - } - } - - it should "get unspent boxes by height from/to inclusive" in { - val appId1: ScanId = ScanId @@ 21.toShort - val appId2: ScanId = ScanId @@ 22.toShort - forAll(trackedBoxGen) { tb0 => - withVersionedStore(10) { store => - val tb1 = tb0.copy(scans = Set(appId1), inclusionHeightOpt = Some(5), spendingHeightOpt = None) - val reg = new WalletRegistry(store)(ws) - WalletRegistry.putBox(emptyBag, tb1).transact(store).get - reg.getBox(tb1.box.id).get.scans shouldBe Set(appId1) - reg.boxesByInclusionHeight(appId1, 1, 4).length shouldBe 0 - reg.boxesByInclusionHeight(appId1, 6, 10).length shouldBe 0 - reg.boxesByInclusionHeight(appId1, 4, 6).length shouldBe 1 - reg.boxesByInclusionHeight(appId1, 5, 6).length shouldBe 1 - reg.boxesByInclusionHeight(appId1, 5, 5).length shouldBe 1 - reg.boxesByInclusionHeight(appId1, 4, 5).length shouldBe 1 - // put another box under the same scan id should result in 2 matches - val tb2 = trackedBoxGen.sample.get.copy(scans = Set(appId1), inclusionHeightOpt = Some(6), spendingHeightOpt = None) - WalletRegistry.putBox(emptyBag, tb2).transact(store).get - reg.boxesByInclusionHeight(appId1, 4, 7).length shouldBe 2 - reg.boxesByInclusionHeight(appId1, 4, 5).length shouldBe 1 - // search should differentiate between scan ids - val tb3 = trackedBoxGen.sample.get.copy(scans = Set(appId2), inclusionHeightOpt = Some(6), spendingHeightOpt = None) - WalletRegistry.putBox(emptyBag, tb3).transact(store).get - reg.boxesByInclusionHeight(appId1, 4, 7).length shouldBe 2 - reg.boxesByInclusionHeight(appId2, 4, 7).length shouldBe 1 - // putting 2 different boxes under same height should result in 2 matches - val tb4 = trackedBoxGen.sample.get.copy(scans = Set(appId2), inclusionHeightOpt = Some(6), spendingHeightOpt = None) - WalletRegistry.putBox(emptyBag, tb4).transact(store).get - reg.boxesByInclusionHeight(appId2, 4, 7).length shouldBe 2 - // putting 2 identical boxes should be idempotent operation - WalletRegistry.putBox(emptyBag, tb4).transact(store).get - reg.boxesByInclusionHeight(appId2, 4, 7).length shouldBe 2 - // spent boxes should be included - val tb5 = trackedBoxGen.sample.get.copy(scans = Set(appId2), inclusionHeightOpt = Some(5), spendingHeightOpt = Some(6)) - WalletRegistry.putBox(emptyBag, tb5).transact(store).get - reg.boxesByInclusionHeight(appId2, 4, 7).length shouldBe 3 - // one spent box and 2 unspent boxes should be present - reg.spentBoxesByInclusionHeight(appId2, 4, 7).length shouldBe 1 - reg.unspentBoxesByInclusionHeight(appId2, 4, 7).length shouldBe 2 - } - } - } - - it should "remove application from a box correctly" in { - val appId: ScanId = ScanId @@ 20.toShort - - forAll(trackedBoxGen) { tb0 => - val tb = tb0.copy(scans = Set(appId)) - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - WalletRegistry.putBox(emptyBag, tb).transact(store).get - reg.getBox(tb.box.id).isDefined shouldBe true - reg.removeScan(tb.box.id, appId).isSuccess shouldBe true - reg.getBox(tb.box.id).isDefined shouldBe false - } - } - - } - - it should "remove box-scan correspondence and then rollback - one app" in { - val scanId: ScanId = ScanId @@ 20.toShort - - forAll(trackedBoxGen) { tb0 => - val tb = tb0.copy(scans = Set(scanId)) - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - val version = scorex.utils.Random.randomBytes() - - WalletRegistry.putBox(emptyBag, tb).transact(store, version).get - reg.getBox(tb.box.id).isDefined shouldBe true - reg.removeScan(tb.box.id, scanId).isSuccess shouldBe true - reg.getBox(tb.box.id).isDefined shouldBe false - reg.rollback(VersionTag @@ Base16.encode(version)).isSuccess shouldBe true - reg.getBox(tb.box.id).isDefined shouldBe false - } - } - } - - it should "remove box-scan correspondence and then rollback - multiple apps" in { - val scanId: ScanId = ScanId @@ 20.toShort - - forAll(trackedBoxGen) { tb0 => - val tb = tb0.copy(scans = Set(PaymentsScanId, scanId)) - withVersionedStore(10) { store => - val reg = new WalletRegistry(store)(ws) - val version = scorex.utils.Random.randomBytes() - - WalletRegistry.putBox(emptyBag, tb).transact(store, version).get - reg.getBox(tb.box.id).get.scans.size shouldBe 2 - reg.removeScan(tb.box.id, scanId).isSuccess shouldBe true - reg.getBox(tb.box.id).get.scans.size shouldBe 1 - reg.rollback(VersionTag @@ Base16.encode(version)).isSuccess shouldBe true - reg.getBox(tb.box.id).get.scans.size shouldBe 1 - reg.getBox(tb.box.id).get.scans shouldBe Set(PaymentsScanId) - } - } - } - - it should "compose keys correctly" in { - val box = trackedBoxGen.sample.get - - forAll { (prefix: Byte, scanId: Short, height: Int, suffix: Byte) => - val key1 = (prefix +: Shorts.toByteArray(scanId)) ++ Array.fill(32)(suffix) - WalletRegistry.composeKey(prefix, ScanId @@ scanId, suffix) shouldBe key1 - - val key2 = (prefix +: Shorts.toByteArray(scanId)) ++ Ints.toByteArray(height) ++ Array.fill(32)(suffix) - WalletRegistry.composeKey(prefix, ScanId @@ scanId, height, suffix) shouldBe key2 - - val id = box.box.id - val key3 = (prefix +: Shorts.toByteArray(scanId)) ++ id - WalletRegistry.composeKeyWithId(prefix, ScanId @@ scanId, id) shouldBe key3 - - val key4 = (prefix +: Shorts.toByteArray(scanId)) ++ Ints.toByteArray(height) ++ id - WalletRegistry.composeKeyWithHeightAndId(prefix, ScanId @@ scanId, height, id) shouldBe key4 - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorageSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorageSpec.scala deleted file mode 100644 index c0a1826bab..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/persistence/WalletStorageSpec.scala +++ /dev/null @@ -1,88 +0,0 @@ -package org.ergoplatform.nodeView.wallet.persistence - -import com.google.common.primitives.Ints -import org.ergoplatform.db.DBSpec -import org.ergoplatform.nodeView.wallet.persistence.WalletStorage.SecretPathsKey -import org.ergoplatform.nodeView.wallet.scanning.{ScanRequest, ScanWalletInteraction} -import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, DerivationPathSerializer} -import org.ergoplatform.utils.generators.WalletGenerators -import org.scalacheck.Gen -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.db.LDBKVStore - -class WalletStorageSpec - extends AnyFlatSpec - with Matchers - with WalletGenerators - with ScalaCheckPropertyChecks - with DBSpec { - - it should "add and read derivation paths" in { - def addPath(store: LDBKVStore, storedPaths: Seq[DerivationPath], derivationPath: DerivationPath): Unit = { - val updatedPaths = (storedPaths :+ derivationPath).toSet - val toInsert = Ints.toByteArray(updatedPaths.size) ++ updatedPaths - .foldLeft(Array.empty[Byte]) { case (acc, path) => - val bytes = DerivationPathSerializer.toBytes(path) - acc ++ Ints.toByteArray(bytes.length) ++ bytes - } - store.insert(SecretPathsKey, toInsert).get - } - - forAll(Gen.nonEmptyListOf(derivationPathGen)) { paths => - withStore { store => - val storage = new WalletStorage(store, settings) - paths.foreach(path => addPath(store, storage.readPaths(), path)) - storage.readPaths() should contain theSameElementsAs paths.toSet - } - } - } - - it should "add and read public keys" in { - forAll(extendedPubKeyListGen) { pubKeys => - withStore { store => - val storage = new WalletStorage(store, settings) - pubKeys.foreach(storage.addPublicKey(_).get) - val keysRead = storage.readAllKeys() - keysRead.length shouldBe pubKeys.length - keysRead should contain theSameElementsAs pubKeys.toSet - } - } - } - - it should "add, remove and read scans" in { - forAll(Gen.nonEmptyListOf(externalScanReqGen)) { externalScanReqs => - withStore { store => - val storage = new WalletStorage(store, settings) - externalScanReqs.foreach(req => storage.addScan(req)) - val storageApps = storage.allScans - val storageRequests = storageApps.map { app => - ScanRequest(app.scanName, app.trackingRule, Some(ScanWalletInteraction.Off), Some(true)) - } - storageRequests.foreach(r => externalScanReqs.contains(r) shouldBe true) - storageApps.map(_.scanId).foreach(storage.removeScan(_).get) - storage.allScans.length shouldBe 0 - } - } - } - - it should "always increase ids" in { - forAll(externalScanReqGen) { externalScanReq => - withStore { store => - val storage = new WalletStorage(store, settings) - val scan = storage.addScan(externalScanReq).get - - storage.lastUsedScanId shouldBe scan.scanId - - storage.removeScan(scan.scanId).get - storage.lastUsedScanId shouldBe scan.scanId - - val scan2 = storage.addScan(externalScanReq).get - storage.lastUsedScanId shouldBe scan2.scanId - storage.lastUsedScanId shouldBe (scan.scanId +1) - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanSpecification.scala deleted file mode 100644 index 120a0e8691..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanSpecification.scala +++ /dev/null @@ -1,24 +0,0 @@ -package org.ergoplatform.nodeView.wallet.scanning - -import io.circe.Json -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators - -class ScanSpecification extends ErgoPropertyTest with WalletGenerators { - import ScanJsonCodecs._ - - property("external scan req json serialization roundtrip") { - forAll(externalScanReqGen) { req => - val j: Json = scanReqEncoder.apply(req) - scanReqDecoder.decodeJson(j).toTry.get == req - } - } - - property("external scan json serialization roundtrip") { - forAll(externalAppGen) { req => - val j: Json = scanEncoder.apply(req) - scanDecoder.decodeJson(j).toTry.get == req - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala deleted file mode 100644 index 4d015ac027..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateJsonCodecsSpecification.scala +++ /dev/null @@ -1,78 +0,0 @@ -package org.ergoplatform.nodeView.wallet.scanning - -import io.circe.parser._ -import org.ergoplatform.ErgoBox -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators -import scorex.util.encode.Base16 -import sigmastate.Values.ByteArrayConstant -import sigmastate.eval.Extensions.ArrayByteOps - -import scala.language.implicitConversions - -class ScanningPredicateJsonCodecsSpecification extends ErgoPropertyTest with WalletGenerators { - - import ScanningPredicateJsonCodecs.{scanningPredicateDecoder, scanningPredicateEncoder} - - private implicit def bacFromBytes(bs: Array[Byte]) = ByteArrayConstant(bs) - - private val complexOr = OrScanningPredicate( - ContainsScanningPredicate(ErgoBox.R1, ByteArrayConstant(Array.fill(32)(1: Byte))), - EqualsScanningPredicate(ErgoBox.R4, ByteArrayConstant(Array.fill(32)(0: Byte))), - ContainsAssetPredicate(Array.fill(32)(0: Byte).toTokenId) - ) - - private val complexAnd = AndScanningPredicate( - ContainsScanningPredicate(ErgoBox.R1, ByteArrayConstant(Array.fill(32)(1: Byte))), - EqualsScanningPredicate(ErgoBox.R4, ByteArrayConstant(Array.fill(32)(1: Byte))), - ContainsAssetPredicate(Array.fill(32)(1: Byte).toTokenId) - ) - - property("json roundtrip for generated predicate") { - forAll(scanningPredicateGen){p => - val j = scanningPredicateEncoder(p) - scanningPredicateDecoder.decodeJson(j).toTry.get == p - } - } - - property("complex or roundtrip") { - val p = complexOr - val j = scanningPredicateEncoder(p) - scanningPredicateDecoder.decodeJson(j).toTry.get == p - } - - property("complex and roundtrip") { - val p = complexAnd - val j = scanningPredicateEncoder(p) - scanningPredicateDecoder.decodeJson(j).toTry.get == p - } - - property("example from EIP-1"){ - val j = parse( - """{"predicate": "and", "args":[{"predicate": "contains", - |"value": "0e2102dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7"}, - |{"predicate": "containsAsset", - |"assetId": "02dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7"}]}""".stripMargin).toOption.get - - val bs = Base16.decode("02dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7").get - scanningPredicateDecoder.decodeJson(j).toTry.get == AndScanningPredicate( - ContainsScanningPredicate(ErgoBox.R1, bs), - ContainsAssetPredicate(bs.toTokenId) - ) - } - - property("example from EIP-1 w. explicit register"){ - val j = parse( - """{"predicate": "and", "args":[{"predicate": "contains", "register": "R4", - |"value": "0e2102dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7"}, - |{"predicate": "containsAsset", - |"assetId": "02dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7"}]}""".stripMargin).toOption.get - - val bs = Base16.decode("02dada811a888cd0dc7a0a41739a3ad9b0f427741fe6ca19700cf1a51200c96bf7").get - scanningPredicateDecoder.decodeJson(j).toTry.get == AndScanningPredicate( - ContainsScanningPredicate(ErgoBox.R4, bs), - ContainsAssetPredicate(bs.toTokenId) - ) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializerSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializerSpecification.scala deleted file mode 100644 index ccd25df6ed..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSerializerSpecification.scala +++ /dev/null @@ -1,22 +0,0 @@ -package org.ergoplatform.nodeView.wallet.scanning - -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators - -class ScanningPredicateSerializerSpecification extends ErgoPropertyTest with WalletGenerators { - - property("complex or roundtrip") { - forAll(scanningPredicateGen) { p => - val bs = ScanningPredicateSerializer.toBytes(p) - ScanningPredicateSerializer.parseBytes(bs) == p - } - } - - property("complex and roundtrip") { - forAll(scanningPredicateGen) { p => - val bs = ScanningPredicateSerializer.toBytes(p) - ScanningPredicateSerializer.parseBytes(bs) == p - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala deleted file mode 100644 index dcfc049dbe..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/nodeView/wallet/scanning/ScanningPredicateSpecification.scala +++ /dev/null @@ -1,229 +0,0 @@ -package org.ergoplatform.nodeView.wallet.scanning - -import io.circe.parser._ -import org.ergoplatform.ErgoBox.R1 -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.ErgoTransactionGenerators -import org.ergoplatform.wallet.serialization.JsonCodecsWrapper -import org.ergoplatform.{ErgoTreePredef, P2PKAddress} -import sigmastate.Values.ByteArrayConstant -import sigmastate.eval.Extensions.ArrayByteOps -import sigmastate.helpers.TestingHelpers._ - -import scala.language.implicitConversions -import scala.util.Random - -class ScanningPredicateSpecification extends ErgoPropertyTest with ErgoTransactionGenerators { - - val testDelay = 720 // to construct mining rewards scripts - - private implicit def bacFromBytes(bs: Array[Byte]) = ByteArrayConstant(bs) - - /** Helper function to create a new array with changed random byte. */ - private def mutateRandomByte(source: Array[Byte]): Array[Byte] = { - val sourceModified = source.clone() - val idx = Random.nextInt(sourceModified.length) - sourceModified.update(idx, ((sourceModified(idx) + 1) % Byte.MaxValue).toByte) - sourceModified - } - - property("equals - p2pk") { - forAll(ergoAddressGen) { p2pkAddress => - //look for exact p2pk script bytes - val box = testBox(value = 1, p2pkAddress.script, creationHeight = 0) - val scriptBytes = p2pkAddress.script.bytes - EqualsScanningPredicate(R1, scriptBytes).filter(box) shouldBe true - - //then change random byte - val scriptBytesModified = mutateRandomByte(scriptBytes) - EqualsScanningPredicate(R1, scriptBytesModified).filter(box) shouldBe false - - //skip first byte in the filter - EqualsScanningPredicate(R1, scriptBytes.tail).filter(box) shouldBe false - } - } - - property("equals - miner prop") { - forAll(proveDlogGen) { pk => - val minerProp = ErgoTreePredef.rewardOutputScript(testDelay, pk) - val mpBytes = minerProp.bytes - - //look for exact miner script bytes - val box = testBox(value = 1, minerProp, creationHeight = 0) - EqualsScanningPredicate(R1, mpBytes).filter(box) shouldBe true - - //then change random byte - val scriptBytesModified = mutateRandomByte(mpBytes) - EqualsScanningPredicate(R1, scriptBytesModified).filter(box) shouldBe false - } - } - - property("contains - p2pk") { - forAll(ergoAddressGen) { p2pkAddress => - //look for exact p2pk script bytes - val box = testBox(value = 1, p2pkAddress.script, creationHeight = 0) - val pkBytes = p2pkAddress.asInstanceOf[P2PKAddress].pubkeyBytes - ContainsScanningPredicate(R1, pkBytes).filter(box) shouldBe true - - //then change random byte in filter - val pkBytesModified = mutateRandomByte(pkBytes) - EqualsScanningPredicate(R1, pkBytesModified).filter(box) shouldBe false - - //skip first byte in the proper filter - ContainsScanningPredicate(R1, pkBytes.tail).filter(box) shouldBe true - } - } - - property("contains - miner prop") { - forAll(ergoAddressGen) { p2pkAddress => - //look for exact p2pk script bytes - val minerProp = ErgoTreePredef.rewardOutputScript(testDelay, p2pkAddress.asInstanceOf[P2PKAddress].pubkey) - val box = testBox(value = 1, minerProp, creationHeight = 0) - val pkBytes = p2pkAddress.asInstanceOf[P2PKAddress].pubkeyBytes - - ContainsScanningPredicate(R1, pkBytes).filter(box) shouldBe true - - //then change random byte in filter - val pkBytesModified = mutateRandomByte(pkBytes) - EqualsScanningPredicate(R1, pkBytesModified).filter(box) shouldBe false - - //skip first byte in the proper filter - ContainsScanningPredicate(R1, pkBytes.tail).filter(box) shouldBe true - } - } - - property("containsAsset") { - forAll(proveDlogGen) { pk => - forAll(assetGen) { case (tokenId, amt) => - val box = testBox(value = 1, pk, creationHeight = 0, additionalTokens = Seq(tokenId -> amt)) - ContainsAssetPredicate(tokenId).filter(box) shouldBe true - - val emptyBox = testBox(value = 1, pk, creationHeight = 0) - ContainsAssetPredicate(tokenId).filter(emptyBox) shouldBe false - - ContainsAssetPredicate(mutateRandomByte(tokenId.toArray).toTokenId).filter(box) shouldBe false - } - } - } - - property("and") { - forAll(ergoAddressGen) { p2pk => - forAll(assetGen) { case (tokenId, amt) => - val box = testBox(value = 1, p2pk.script, creationHeight = 0, additionalTokens = Seq(tokenId -> amt)) - - //box contains both asset and p2pk script - AndScanningPredicate(ContainsAssetPredicate(tokenId), ContainsScanningPredicate(R1, p2pk.contentBytes)) - .filter(box) shouldBe true - - AndScanningPredicate( - EqualsScanningPredicate(R1, p2pk.script.bytes), - ContainsScanningPredicate(R1, p2pk.contentBytes) - ).filter(box) shouldBe true - - AndScanningPredicate( - ContainsAssetPredicate(mutateRandomByte(tokenId.toArray).toTokenId), - ContainsScanningPredicate(R1, p2pk.contentBytes) - ).filter(box) shouldBe false - - AndScanningPredicate( - ContainsAssetPredicate(tokenId), - ContainsScanningPredicate(R1, mutateRandomByte(p2pk.contentBytes)) - ).filter(box) shouldBe false - } - } - } - - property("or") { - forAll(ergoAddressGen) { p2pk => - forAll(assetGen) { case (tokenId, amt) => - val box = testBox(value = 1, p2pk.script, creationHeight = 0, additionalTokens = Seq(tokenId -> amt)) - - //box contains both asset and p2pk script - OrScanningPredicate(ContainsAssetPredicate(tokenId), ContainsScanningPredicate(R1, p2pk.contentBytes)) - .filter(box) shouldBe true - - OrScanningPredicate( - EqualsScanningPredicate(R1, p2pk.script.bytes), - ContainsScanningPredicate(R1, p2pk.contentBytes) - ).filter(box) shouldBe true - - OrScanningPredicate( - ContainsAssetPredicate(mutateRandomByte(tokenId.toArray).toTokenId), - ContainsScanningPredicate(R1, p2pk.contentBytes) - ).filter(box) shouldBe true - - OrScanningPredicate( - ContainsAssetPredicate(tokenId), - ContainsScanningPredicate(R1, mutateRandomByte(p2pk.contentBytes)) - ).filter(box) shouldBe true - - OrScanningPredicate( - ContainsAssetPredicate(mutateRandomByte(tokenId.toArray).toTokenId), - ContainsScanningPredicate(R1, mutateRandomByte(p2pk.contentBytes)) - ).filter(box) shouldBe false - } - } - } - - property("and - complex case #1 - with deserialization"){ - val scanString = - """ - |{ - | "scanId": 80, - | "scanName": "Local Oracle Datapoint Scan", - | "trackingRule": { - | "predicate": "and", - | "args": [ - | { - | "predicate": "containsAsset", - | "assetId": "12caaacb51c89646fac9a3786eb98d0113bd57d68223ccc11754a4f67281daed" - | }, - | { - | "predicate": "equals", - | "register": "R1", - | "value": "0edf03100604000400050004000e20b662db51cf2dc39f110a021c2a31c74f0a1a18ffffbf73e8a051a7b8c0f09ebc0eca02100e040004000e2012caaacb51c89646fac9a3786eb98d0113bd57d68223ccc11754a4f67281daed0500040004140580dac4090402048092f401040201010402058092f4010400d804d601b2a5730000d602b5db6501fed9010263ed93e4c67202050ec5a7938cb2db63087202730100017302d603b17202d6049db072027303d9010441639a8c720401e4c68c72040206057e720305ea02d1edededededededed93c27201e4c6a7060e917203730493db63087201db6308a793e4c672010405720493e4c6720105049ae4c6a70504730592c17201730693e4c672010405720492c1720199c1a77e9c9a720373077308058cb0720286027309730ad901053c400163d802d6078c720501d6088c72070186029a7208730beded8c72070293c2b2a5720800d0cde4c68c720502040792c1b2a5720800730c02b2ad7202d9010563cde4c672050407730d00d803d601b2a5730000d602e4c6a70407d603b2db6501fe730100ea02d1ededededed93e4c672010407720293e4c67201050ec5720391e4c672010605730293c27201c2a793db63087201db6308a7ed938cb2db6308720373030001730493c272037305cd7202" - | }, - | { - | "predicate": "equals", - | "register": "R4", - | "value": "07029f2230dbe53f6b84d8a884a3407c3dffe43daf8037445441be7cdcd261feeaa4" - | } - | ] - | }, - | "walletInteraction": "off", - | "removeOffchain": true - | } - """.stripMargin - - val scanJson = parse(scanString).toOption.get - val scan = ScanJsonCodecs.scanDecoder.decodeJson(scanJson).toOption.get - - val boxString = - """ - |{ - | "boxId": "9441cf85bb564c72426b5eca49bce5f6cb27778c598ad02f34ca4358027b3a44", - | "value": 2000000, - | "ergoTree": "100604000400050004000e20b662db51cf2dc39f110a021c2a31c74f0a1a18ffffbf73e8a051a7b8c0f09ebc0eca02100e040004000e2012caaacb51c89646fac9a3786eb98d0113bd57d68223ccc11754a4f67281daed0500040004140580dac4090402048092f401040201010402058092f4010400d804d601b2a5730000d602b5db6501fed9010263ed93e4c67202050ec5a7938cb2db63087202730100017302d603b17202d6049db072027303d9010441639a8c720401e4c68c72040206057e720305ea02d1edededededededed93c27201e4c6a7060e917203730493db63087201db6308a793e4c672010405720493e4c6720105049ae4c6a70504730592c17201730693e4c672010405720492c1720199c1a77e9c9a720373077308058cb0720286027309730ad901053c400163d802d6078c720501d6088c72070186029a7208730beded8c72070293c2b2a5720800d0cde4c68c720502040792c1b2a5720800730c02b2ad7202d9010563cde4c672050407730d00d803d601b2a5730000d602e4c6a70407d603b2db6501fe730100ea02d1ededededed93e4c672010407720293e4c67201050ec5720391e4c672010605730293c27201c2a793db63087201db6308a7ed938cb2db6308720373030001730493c272037305cd7202", - | "assets": [ - | { - | "tokenId": "12caaacb51c89646fac9a3786eb98d0113bd57d68223ccc11754a4f67281daed", - | "amount": 1 - | } - | ], - | "creationHeight": 280831, - | "additionalRegisters": { - | "R4": "07029f2230dbe53f6b84d8a884a3407c3dffe43daf8037445441be7cdcd261feeaa4", - | "R5": "0e0101" - | }, - | "transactionId": "dfad960e6fb085f10e9b700f5631251b11209e7ed09a56c94d8bd91452226344", - | "index": 1 - | } - """.stripMargin - - val boxJson = parse(boxString).toOption.get - val box = JsonCodecsWrapper.ergoBoxDecoder.decodeJson(boxJson).toOption.get - - scan.trackingRule.filter(box) shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala deleted file mode 100644 index 46a670cab6..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/reemission/ReemissionRulesSpec.scala +++ /dev/null @@ -1,208 +0,0 @@ -package org.ergoplatform.reemission - -import org.ergoplatform._ -import org.ergoplatform.settings.{MonetarySettings, ReemissionSettings} -import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestConstants} -import scorex.crypto.hash.Blake2b256 -import scorex.util.ModifierId -import sigma.Colls -import sigmastate.AvlTreeData -import sigmastate.TrivialProp.TrueProp -import sigmastate.eval.Digest32Coll -import sigmastate.helpers.TestingHelpers.testBox -import sigmastate.helpers.{ContextEnrichingTestProvingInterpreter, ErgoLikeContextTesting, ErgoLikeTestInterpreter} -import sigmastate.interpreter.Interpreter.emptyEnv - -import scala.util.{Failure, Success, Try} - -// done similarly to ErgoScriptPredefSpec in sigma repo -class ReemissionRulesSpec extends ErgoPropertyTest with ErgoTestConstants { - - private val ms = MonetarySettings() - private val checkReemissionRules: Boolean = true - private val emissionNftId: ModifierId = ModifierId @@ "06f29034fb69b23d519f84c4811a19694b8cdc2ce076147aaa050276f0b840f4" - private val reemissionTokenId: ModifierId = ModifierId @@ "01345f0ed87b74008d1c46aefd3e7ad6ee5909a2324f2899031cdfee3cc1e022" - private val reemissionNftId: ModifierId = ModifierId @@ "06f2c3adfe52304543f7b623cc3fccddc0174a7db52452fef8e589adacdfdfee" - private val activationHeight: Int = 0 - private val reemissionStartHeight: Int = 100 - private val injectionBoxBytesEncoded: ModifierId = ModifierId @@ "a0f9e1b5fb011003040005808098f4e9b5ca6a0402d1ed91c1b2a4730000730193c5a7c5b2a4730200f6ac0b0201345f0ed87b74008d1c46aefd3e7ad6ee5909a2324f2899031cdfee3cc1e02280808cfaf49aa53506f29034fb69b23d519f84c4811a19694b8cdc2ce076147aaa050276f0b840f40100325c3679e7e0e2f683e4a382aa74c2c1cb989bb6ad6a1d4b1c5a021d7b410d0f00" - private val rs = ReemissionSettings(checkReemissionRules, emissionNftId, reemissionTokenId, - reemissionNftId, activationHeight, reemissionStartHeight, injectionBoxBytesEncoded) - - private val rr = new ReemissionRules(rs) - - private val reemissionBoxAssets = Colls.fromItems((Digest32Coll @@ rs.reemissionNftIdBytes) -> 1L) - - private val fakeMessage = Blake2b256("Hello World") - - private def prover = new ContextEnrichingTestProvingInterpreter - private def verifier = new ErgoLikeTestInterpreter - private val prop = rr.reemissionBoxProp(ms) - - def checkRewardsTx(nextHeight: Int, - pkBytes: Array[Byte], - inputBoxes: IndexedSeq[ErgoBox], - spendingTransaction: ErgoLikeTransaction, - expectedValidity: Boolean) = { - val ctx = ErgoLikeContextTesting( - currentHeight = nextHeight, - lastBlockUtxoRoot = AvlTreeData.dummy, - minerPubkey = pkBytes, - boxesToSpend = inputBoxes, - spendingTransaction, - self = inputBoxes.head, - 1: Byte) //activated script version - Try(prover.prove(emptyEnv, prop, ctx, fakeMessage).get) match { - case Success(pr) => - verifier.verify(emptyEnv, prop, ctx, pr, fakeMessage).get._1 shouldBe expectedValidity - case Failure(e) if expectedValidity => - throw new Exception("Unexpected exception thrown: ", e) - case _ => - } - } - - ignore("reemission rules test vectors") { - - } - - property("reemissionBoxProp - spending path") { - val minerPk = prover.dlogSecrets.head.publicImage - val pkBytes = minerPk.pkBytes - val minerProp = ErgoTreePredef.rewardOutputScript(ms.minerRewardDelay, minerPk) - - val currentHeight = rs.reemissionStartHeight - val nextHeight = currentHeight + 1 - - val initialErgValue = 1000000000000L - val reemissionBox = testBox(initialErgValue, prop, currentHeight, reemissionBoxAssets.toArray, Map()) - - val reemissionReward = rr.reemissionRewardPerBlock - - val inputBoxes = IndexedSeq(reemissionBox) - val inputs = inputBoxes.map(b => Input(b.id, emptyProverResult)) - - val newReemissionBox = new ErgoBoxCandidate(reemissionBox.value - reemissionReward, prop, nextHeight, reemissionBoxAssets) - val minerBox = new ErgoBoxCandidate(reemissionReward, minerProp, nextHeight) - - val spendingTransaction = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox, minerBox)) - - // normal execution - checkRewardsTx(nextHeight, pkBytes, inputBoxes, spendingTransaction, true) - - // miner tries to take too much from reemission contract - val newReemissionBox2 = new ErgoBoxCandidate(reemissionBox.value - reemissionReward - 1, prop, nextHeight, reemissionBoxAssets) - val minerBox2 = new ErgoBoxCandidate(reemissionReward + 1, minerProp, nextHeight) - val spendingTransaction2 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox2, minerBox2)) - checkRewardsTx(nextHeight, pkBytes, inputBoxes, spendingTransaction2, false) - - //... and it is not okay to take less even - val newReemissionBox3 = new ErgoBoxCandidate(reemissionBox.value - reemissionReward + 1, prop, nextHeight, reemissionBoxAssets) - val minerBox3 = new ErgoBoxCandidate(reemissionReward - 1, minerProp, nextHeight) - val spendingTransaction3 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox3, minerBox3)) - checkRewardsTx(nextHeight, pkBytes, inputBoxes, spendingTransaction3, false) - - // re-emission NFT must be preserved - val newReemissionBox4 = new ErgoBoxCandidate(reemissionBox.value - reemissionReward, prop, nextHeight, Colls.emptyColl) - val spendingTransaction4 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox4, minerBox)) - checkRewardsTx(nextHeight, pkBytes, inputBoxes, spendingTransaction4, false) - - // not possible to charge before re-emission start - val nextHeight5 = currentHeight - 10 - val emissionBox5 = testBox(initialErgValue, prop, nextHeight5 - 1, reemissionBoxAssets.toArray, Map()) - val inputBoxes5 = IndexedSeq(emissionBox5) - val inputs5 = inputBoxes5.map(b => Input(b.id, emptyProverResult)) - val newReemissionBox5 = new ErgoBoxCandidate(emissionBox5.value - reemissionReward, prop, nextHeight5, reemissionBoxAssets) - val minerBox5 = new ErgoBoxCandidate(reemissionReward, minerProp, nextHeight5) - val spendingTransaction5 = ErgoLikeTransaction(inputs5, IndexedSeq(newReemissionBox5, minerBox5)) - checkRewardsTx(nextHeight5, pkBytes, inputBoxes5, spendingTransaction5, false) - - // can be spent to miner pubkey only - val prover6 = new ContextEnrichingTestProvingInterpreter - val minerPk6 = prover6.dlogSecrets.head.publicImage - val pkBytes6 = minerPk6.pkBytes - checkRewardsTx(nextHeight, pkBytes6, inputBoxes, spendingTransaction, false) - - // we modify reward delay here, not PK - val minerProp7 = ErgoTreePredef.rewardOutputScript(ms.minerRewardDelay - 1, minerPk) - val minerBox7 = new ErgoBoxCandidate(reemissionReward, minerProp7, nextHeight) - val spendingTransaction7 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox, minerBox7)) - checkRewardsTx(nextHeight, pkBytes, inputBoxes, spendingTransaction7, false) - } - - // also testing payToReemission contract - property("reemissionBoxProp - merging path") { - val minerPk = prover.dlogSecrets.head.publicImage - val pkBytes = minerPk.pkBytes - - val rewardsProp = prop - val pay2RewardsProp = rr.payToReemission - - val mergedValue = 100000000L - - val currentHeight = rs.reemissionStartHeight - 1 - - val pay2RBox = testBox(mergedValue, pay2RewardsProp, currentHeight, reemissionBoxAssets.toArray, Map()) - val reemissionBox = testBox(mergedValue * 100, rewardsProp, currentHeight, reemissionBoxAssets.toArray, Map()) - - val inputBoxes = IndexedSeq(reemissionBox, pay2RBox) - val inputs = inputBoxes.map(b => Input(b.id, emptyProverResult)) - - val feeValue = 10000000L - - // merging with 1 box - successful case - val newReemissionBox = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue, prop, currentHeight, reemissionBoxAssets) - val feeBox = new ErgoBoxCandidate(feeValue, TrueProp, currentHeight) - val spendingTransaction = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox, feeBox)) - - checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction, true) - - // merging with 2 boxex - successful case - val inputBoxes2 = IndexedSeq(reemissionBox, pay2RBox, pay2RBox) - val inputs2 = inputBoxes2.map(b => Input(b.id, emptyProverResult)) - val newReemissionBox2 = new ErgoBoxCandidate(reemissionBox.value + 2 * mergedValue - feeValue, prop, currentHeight, reemissionBoxAssets) - val spendingTransaction2 = ErgoLikeTransaction(inputs2, IndexedSeq(newReemissionBox2, feeBox)) - - checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction2, true) - - // paying too high fee - val newReemissionBox3 = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue - 1, prop, currentHeight, reemissionBoxAssets) - val feeBox3 = new ErgoBoxCandidate(feeValue + 1, TrueProp, currentHeight) - val spendingTransaction3 = ErgoLikeTransaction(inputs2, IndexedSeq(newReemissionBox3, feeBox3)) - - checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction3, false) - - // reemission NFT must be preserved - val newReemissionBox4 = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue, prop, currentHeight) - val spendingTransaction4 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox4, feeBox)) - - checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction4, false) - - // reemission box value must be increased - val feeValue5 = mergedValue - val newReemissionBox5 = new ErgoBoxCandidate(reemissionBox.value + mergedValue - feeValue5, prop, currentHeight, reemissionBoxAssets) - val feeBox5 = new ErgoBoxCandidate(feeValue5, TrueProp, currentHeight) - val spendingTransaction5 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox5, feeBox5)) - checkRewardsTx(currentHeight, pkBytes, inputBoxes, spendingTransaction5, false) - - // pay-2-reemission box can be spent only with a box with reemission NFT as input #0 - val reemissionBoxAssets6 = Colls.fromItems( - (Digest32Coll @@ rs.reemissionNftIdBytes.reverse) -> 1L - ) - val newReemissionBox6 = new ErgoBoxCandidate( - reemissionBox.value + mergedValue - feeValue, - prop, currentHeight, reemissionBoxAssets6) - val spendingTransaction6 = ErgoLikeTransaction(inputs, IndexedSeq(newReemissionBox6, feeBox)) - - val ctx = ErgoLikeContextTesting( - currentHeight = currentHeight, - lastBlockUtxoRoot = AvlTreeData.dummy, - minerPubkey = pkBytes, - boxesToSpend = inputBoxes, - spendingTransaction6, - self = inputBoxes(1), - 0) - - prover.prove(emptyEnv, pay2RewardsProp, ctx, fakeMessage).isFailure shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala b/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala deleted file mode 100644 index f40b10c22a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanity.scala +++ /dev/null @@ -1,129 +0,0 @@ -package org.ergoplatform.sanity - -import akka.actor.ActorRef -import org.ergoplatform.ErgoBox -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock} -import org.ergoplatform.network.{ErgoNodeViewSynchronizer, ErgoSyncTracker} -import org.ergoplatform.nodeView.NodeViewSynchronizerTests -import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoSyncInfo, ErgoSyncInfoMessageSpec} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.{DigestState, ErgoState, UtxoState} -import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.settings.Constants.HashLength -import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers} -import org.scalacheck.Gen -import scorex.core.network.DeliveryTracker -import scorex.core.{PersistentNodeViewModifier, bytesToId} -import scorex.crypto.authds.ADDigest -import scorex.crypto.hash.{Blake2b256, Digest32} -import scorex.testkit.generators.{ModifierProducerTemplateItem, SynInvalid, Valid} -import scorex.testkit.properties._ -import scorex.testkit.properties.mempool.{MempoolRemovalTest, MempoolTransactionsTest} -import scorex.testkit.properties.state.StateApplicationTest -import scorex.utils.Random - -import scala.concurrent.ExecutionContext -import scala.concurrent.duration._ - -trait ErgoSanity[ST <: ErgoState[ST]] extends NodeViewSynchronizerTests[ST] - with StateApplicationTest[ST] - with MempoolTransactionsTest - with MempoolRemovalTest - with HistoryTests - with ErgoTestHelpers - with HistoryTestHelpers { - - - override val memPool: MPool = ErgoMemPool.empty(settings) - - //Generators - override lazy val transactionGenerator: Gen[ErgoTransaction] = invalidErgoTransactionGen - override lazy val unconfirmedTxGenerator: Gen[UnconfirmedTransaction] = - invalidErgoTransactionGen.map(tx => UnconfirmedTransaction(tx, None)) - override lazy val memPoolGenerator: Gen[MPool] = emptyMemPoolGen - - override def syntacticallyValidModifier(history: HT): Header = { - val bestTimestamp = history.bestHeaderOpt.map(_.timestamp + 1).getOrElse(System.currentTimeMillis()) - - powScheme.prove( - history.bestHeaderOpt, - Header.InitialVersion, - settings.chainSettings.initialNBits, - ADDigest @@ Array.fill(HashLength + 1)(0.toByte), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Math.max(System.currentTimeMillis(), bestTimestamp), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Array.fill(3)(0: Byte), - defaultMinerSecretNumber - ).get - } - - override def syntacticallyInvalidModifier(history: HT): PM = - syntacticallyValidModifier(history).copy(parentId = bytesToId(Random.randomBytes(32))) - - private val hf = Blake2b256 - - def makeSyntacticallyInvalid(mod: PM): PM = mod match { - case fb: ErgoFullBlock => - val parentId = fb.header.parentId - val header = fb.header.copy(parentId = bytesToId(hf(parentId))) - fb.copy(header = header) - case h: Header => h.copy(parentId = bytesToId(hf(h.parentId))) - case v => v - } - - def customModifiers(history: HT, - state: ST, - template: Seq[ModifierProducerTemplateItem]): Seq[PM] = - template.zip(totallyValidModifiers(history, state, template.length)) - .map { case (templateItem, mod) => - templateItem match { - case Valid => mod - case SynInvalid => makeSyntacticallyInvalid(mod) - } - } - - class SyncronizerMock(networkControllerRef: ActorRef, - viewHolderRef: ActorRef, - syncInfoSpec: ErgoSyncInfoMessageSpec.type, - settings: ErgoSettings, - syncTracker: ErgoSyncTracker, - deliveryTracker: DeliveryTracker) - (implicit ec: ExecutionContext) extends ErgoNodeViewSynchronizer( - networkControllerRef, - viewHolderRef, - syncInfoSpec, - settings, - syncTracker, - deliveryTracker)(ec) { - - protected def broadcastInvForNewModifier(mod: PersistentNodeViewModifier): Unit = { - mod match { - case fb: ErgoFullBlock if fb.header.isNew(1.hour) => - fb.toSeq.foreach(s => broadcastModifierInv(s)) - case h: Header if h.isNew(1.hour) => - broadcastModifierInv(h) - case _ => - } - } - } - -} - -object ErgoSanity { - type TX = ErgoTransaction - type B = ErgoBox - type PM = BlockSection - type CTM = BlockTransactions - type SI = ErgoSyncInfo - type HT = ErgoHistory - type UTXO_ST = UtxoState - type DIGEST_ST = DigestState - type MPool = ErgoMemPool - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala b/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala deleted file mode 100644 index d9b07a50e7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala +++ /dev/null @@ -1,107 +0,0 @@ -package org.ergoplatform.sanity - -import akka.actor.{ActorRef, ActorSystem, Props} -import akka.testkit.TestProbe -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.history.header.HeaderSerializer -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool} -import org.ergoplatform.network.ErgoSyncTracker -import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.wrapped.{WrappedDigestState, WrappedUtxoState} -import org.ergoplatform.nodeView.state.{DigestState, StateType} -import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings -import org.scalacheck.Gen -import scorex.core.idToBytes -import scorex.core.network.{ConnectedPeer, DeliveryTracker} -import scorex.core.network.peer.PeerInfo -import scorex.core.serialization.ErgoSerializer - -import scala.concurrent.ExecutionContextExecutor - -class ErgoSanityDigest extends ErgoSanity[DIGEST_ST] { - - override val historyGen: Gen[HT] = - generateHistory(verifyTransactions = true, StateType.Digest, PoPoWBootstrap = false, -1) - - override val stateGen: Gen[WrappedDigestState] = { - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)).map { wus => - val digestState = DigestState.create(Some(wus.version), Some(wus.rootDigest), createTempDir, settings) - new WrappedDigestState(digestState, wus, settings) - } - } - - override def semanticallyValidModifier(state: DIGEST_ST): PM = - validFullBlock(None, state.asInstanceOf[WrappedDigestState].wrappedUtxoState) - - override def semanticallyInvalidModifier(state: DIGEST_ST): PM = invalidErgoFullBlockGen.sample.get - - override def totallyValidModifier(history: HT, state: DIGEST_ST): PM = { - val parentOpt = history.bestFullBlockOpt - validFullBlock(parentOpt, state.asInstanceOf[WrappedDigestState].wrappedUtxoState).header - } - - override def totallyValidModifiers(history: HT, state: DIGEST_ST, count: Int): Seq[PM] = { - require(count >= 1) - val blockOpt = history.bestFullBlockOpt - (0 until count).foldLeft((blockOpt, Seq.empty[PM])) { case (acc, _) => - val pm = validFullBlock(blockOpt, state.asInstanceOf[WrappedDigestState].wrappedUtxoState) - (Some(pm), acc._2 :+ pm) - }._2.map(_.asInstanceOf[ErgoFullBlock].header) - } - - override def nodeViewSynchronizer(implicit system: ActorSystem): - (ActorRef, SI, PM, TX, ConnectedPeer, TestProbe, TestProbe, TestProbe, TestProbe, ErgoSerializer[PM]) = { - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val h = historyGen.sample.get - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val s = stateGen.sample.get - val settings = ErgoSettings.read() - val pool = ErgoMemPool.empty(settings) - val v = h.bestFullBlockIdOpt.orElse(h.bestHeaderIdOpt) - v.foreach(id => s.store.update(idToBytes(id), Seq(), Seq()).get) - implicit val ec: ExecutionContextExecutor = system.dispatcher - val ncProbe = TestProbe("NetworkControllerProbe") - val vhProbe = TestProbe("ViewHolderProbe") - val pchProbe = TestProbe("PeerHandlerProbe") - val eventListener = TestProbe("EventListener") - val syncTracker = ErgoSyncTracker(settings.scorexSettings.network) - val deliveryTracker: DeliveryTracker = DeliveryTracker.empty(settings) - val ref = system.actorOf(Props( - new SyncronizerMock( - ncProbe.ref, - vhProbe.ref, - ErgoSyncInfoMessageSpec, - settings, - syncTracker, - deliveryTracker - ) - )) - val m = totallyValidModifier(h, s) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val tx = validErgoTransactionGenTemplate(minAssets = 0, maxAssets = 0).sample.get._2 - - - val peerInfo = PeerInfo(defaultPeerSpec, Long.MaxValue, None, 0L) - - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val p: ConnectedPeer = ConnectedPeer( - connectionIdGen.sample.get, - pchProbe.ref, - Some(peerInfo) - ) - ref ! ChangedHistory(h) - ref ! ChangedMempool(pool) - val serializer: ErgoSerializer[PM] = HeaderSerializer.asInstanceOf[ErgoSerializer[PM]] - (ref, h.syncInfoV1, m, tx, p, pchProbe, ncProbe, vhProbe, eventListener, serializer) - } - - override def modifierWithTransactions(memoryPoolOpt: Option[MPool], customTransactionsOpt: Option[Seq[TX]]): CTM = { - val boxHolder = boxesHolderGen.sample.get - val txs = validTransactionsFromBoxHolder(boxHolder)._1 - val id = modifierIdGen.sample.get - BlockTransactions(id, 1: Byte, txs) - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala b/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala deleted file mode 100644 index ef6107e35b..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala +++ /dev/null @@ -1,101 +0,0 @@ -package org.ergoplatform.sanity - -import akka.actor.{ActorRef, ActorSystem, Props} -import akka.testkit.TestProbe -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool} -import org.ergoplatform.network.ErgoSyncTracker -import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.ErgoTestHelpers -import org.scalacheck.Gen -import scorex.core.network.{ConnectedPeer, DeliveryTracker} -import scorex.core.network.peer.PeerInfo -import scorex.core.serialization.ErgoSerializer - -import scala.concurrent.ExecutionContextExecutor - -class ErgoSanityUTXO extends ErgoSanity[UTXO_ST] with ErgoTestHelpers { - - override val historyGen: Gen[HT] = - generateHistory(verifyTransactions = true, StateType.Utxo, PoPoWBootstrap = false, blocksToKeep = -1) - - override val stateGen: Gen[WrappedUtxoState] = - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)) - - override def semanticallyValidModifier(state: UTXO_ST): PM = { - statefulyValidFullBlock(state.asInstanceOf[WrappedUtxoState]) - } - - override def semanticallyInvalidModifier(state: UTXO_ST): PM = invalidErgoFullBlockGen.sample.get - - override def totallyValidModifier(history: HT, state: UTXO_ST): PM = { - val parentOpt = history.bestFullBlockOpt - validFullBlock(parentOpt, state.asInstanceOf[WrappedUtxoState]).header - } - - override def totallyValidModifiers(history: HT, state: UTXO_ST, count: Int): Seq[PM] = { - require(count >= 1) - val headerOpt = history.bestFullBlockOpt - (0 until count).foldLeft((headerOpt, Seq.empty[PM])) { case (acc, _) => - val pm = validFullBlock(headerOpt, state.asInstanceOf[WrappedUtxoState]) - (Some(pm), acc._2 :+ pm) - }._2.map(_.asInstanceOf[ErgoFullBlock].header) - } - - override def nodeViewSynchronizer(implicit system: ActorSystem): - (ActorRef, SI, PM, TX, ConnectedPeer, TestProbe, TestProbe, TestProbe, TestProbe, ErgoSerializer[PM]) = { - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val h = historyGen.sample.get - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val s = stateGen.sample.get - val settings = ErgoSettings.read() - val pool = ErgoMemPool.empty(settings) - implicit val ec: ExecutionContextExecutor = system.dispatcher - val ncProbe = TestProbe("NetworkControllerProbe") - val vhProbe = TestProbe("ViewHolderProbe") - val pchProbe = TestProbe("PeerHandlerProbe") - val eventListener = TestProbe("EventListener") - val syncTracker = ErgoSyncTracker(settings.scorexSettings.network) - val deliveryTracker: DeliveryTracker = DeliveryTracker.empty(settings) - val ref = system.actorOf(Props( - new SyncronizerMock( - ncProbe.ref, - vhProbe.ref, - ErgoSyncInfoMessageSpec, - settings, - syncTracker, - deliveryTracker) - )) - val m = totallyValidModifier(h, s) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val tx = validErgoTransactionGenTemplate(minAssets = 0, maxAssets = 0).sample.get._2 - - - val peerInfo = PeerInfo(defaultPeerSpec, System.currentTimeMillis(), None, 0L) - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val p: ConnectedPeer = ConnectedPeer( - connectionIdGen.sample.get, - pchProbe.ref, - Some(peerInfo) - ) - ref ! ChangedHistory(h) - ref ! ChangedMempool(pool) - val serializer: ErgoSerializer[PM] = HeaderSerializer.asInstanceOf[ErgoSerializer[PM]] - (ref, h.syncInfoV1, m, tx, p, pchProbe, ncProbe, vhProbe, eventListener, serializer) - } - - override def modifierWithTransactions(memoryPoolOpt: Option[MPool], customTransactionsOpt: Option[Seq[TX]]): CTM = { - val boxHolder = boxesHolderGen.sample.get - val txs = validTransactionsFromBoxHolder(boxHolder)._1 - val id = modifierIdGen.sample.get - BlockTransactions(id, Header.InitialVersion, txs) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/serialization/ErgoBoxSerializerSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/serialization/ErgoBoxSerializerSpec.scala deleted file mode 100644 index 7fdf9d2c17..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/serialization/ErgoBoxSerializerSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -package org.ergoplatform.serialization - -import org.ergoplatform.ErgoBox -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.wallet.boxes.ErgoBoxSerializer -import scorex.util.serialization.VLQByteStringWriter -import scala.util.Try - -class ErgoBoxSerializerSpec extends ErgoPropertyTest { - - property("ErgoBox serialization") { - forAll(ergoBoxGen) { b: ErgoBox => - val bs = ErgoBoxSerializer.toBytes(b) - val b2 = ErgoBoxSerializer.parseBytes(bs) - b shouldBe b2 - } - } - - property("creation height overflow") { - // helper method which creates bypassing Scala API, via changing binary representation - def overflowHeight(box: ErgoBox): Try[ErgoBox] = { - val hBytes = (new VLQByteStringWriter).putUInt(box.creationHeight).toBytes - - val bs = ErgoBoxSerializer.toBytes(box) - val pos = bs.indexOfSlice(hBytes, 0) - - val before = bs.slice(0, pos) - val after = bs.slice(pos + hBytes.length, bs.length) - - val overflowHeight = 0xFFFFFFFFL - val overBytes = (new VLQByteStringWriter).putUInt(overflowHeight).toBytes - - ErgoBoxSerializer.parseBytesTry(before ++ overBytes ++ after) - } - - forAll(ergoBoxGen) { b: ErgoBox => - val h = Int.MaxValue - val ob = new ErgoBox(b.value, b.ergoTree, b.additionalTokens, b.additionalRegisters, b.transactionId, b.index, h) - // starting from 5.0.0 sigma interpreter, Int overflow is thrown - overflowHeight(ob).isFailure shouldBe true - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala b/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala deleted file mode 100644 index 016696d708..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala +++ /dev/null @@ -1,195 +0,0 @@ -package org.ergoplatform.serialization - -import io.circe.syntax._ -import io.circe.{ACursor, Decoder, Encoder, Json} -import org.ergoplatform.ErgoBox -import org.ergoplatform.ErgoBox.{AdditionalRegisters, NonMandatoryRegisterId} -import org.ergoplatform.http.api.ApiCodecs -import org.ergoplatform.http.api.ApiEncoderOption.HideDetails.implicitValue -import org.ergoplatform.http.api.ApiEncoderOption.{Detalization, ShowDetails} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.popow.NipopowProof -import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction -import org.ergoplatform.nodeView.wallet.requests._ -import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey} -import org.ergoplatform.settings.{Algos, ErgoSettings} -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators -import org.ergoplatform.wallet.Constants.ScanId -import org.ergoplatform.wallet.boxes.TrackedBox -import org.scalatest.Inspectors -import sigmastate.SType -import sigmastate.Values.{ErgoTree, EvaluatedValue} - -import scala.util.Random - - -class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with ApiCodecs { - - property("ErgoFullBlock should be encoded into JSON and decoded back correctly") { - - val (st, bh) = createUtxoState(settings) - val block: ErgoFullBlock = validFullBlock(parentOpt = None, st, bh) - - val blockJson: Json = block.asJson - val blockDecoded: ErgoFullBlock = blockJson.as[ErgoFullBlock].toTry.get - - blockDecoded shouldEqual block - } - - property("ErgoBox should be converted into json correctly") { - forAll(ergoBoxGen) { box => - checkErgoBox(box.asJson.hcursor, box) - } - } - - property("TrackedBox should be serialized to json") { - forAll(trackedBoxGen) { b => - checkTrackedBox(b.asJson.hcursor, b) - import ShowDetails.implicitValue - checkTrackedBox(b.asJson.hcursor, b) - } - } - - property("PaymentRequest should be serialized to json") { - val ergoSettings = ErgoSettings.read() - implicit val requestEncoder: Encoder[PaymentRequest] = new PaymentRequestEncoder(ergoSettings) - implicit val requestDecoder: Decoder[PaymentRequest] = new PaymentRequestDecoder(ergoSettings) - forAll(paymentRequestGen) { request => - val json = request.asJson - val parsingResult = json.as[PaymentRequest] - parsingResult.isRight shouldBe true - val restored = parsingResult.value - restored.address shouldEqual request.address - restored.value shouldEqual request.value - restored.registers shouldEqual request.registers - Inspectors.forAll(restored.assets.zip(request.assets)) { - case ((restoredToken, restoredValue), (requestToken, requestValue)) => - restoredToken shouldEqual requestToken - restoredValue shouldEqual requestValue - } - } - } - - property("BurnTokensRequest should be serialized to json") { - implicit val requestEncoder: Encoder[BurnTokensRequest] = new BurnTokensRequestEncoder() - implicit val requestDecoder: Decoder[BurnTokensRequest] = new BurnTokensRequestDecoder() - forAll(burnTokensRequestGen) { request => - val json = request.asJson - val parsingResult = json.as[BurnTokensRequest] - parsingResult.isRight shouldBe true - val restored = parsingResult.value - Inspectors.forAll(restored.assetsToBurn.zip(request.assetsToBurn)) { - case ((restoredToken, restoredValue), (requestToken, requestValue)) => - restoredToken shouldEqual requestToken - restoredValue shouldEqual requestValue - } - } - } - - property("AssetIssueRequest should be serialized to json") { - val ergoSettings = ErgoSettings.read() - implicit val requestEncoder: Encoder[AssetIssueRequest] = new AssetIssueRequestEncoder(ergoSettings) - implicit val requestDecoder: Decoder[AssetIssueRequest] = new AssetIssueRequestDecoder(ergoSettings) - forAll(assetIssueRequestGen) { request => - val json = request.asJson - val parsingResult = json.as[AssetIssueRequest] - parsingResult.isRight shouldBe true - val restored = parsingResult.value - restored.addressOpt shouldEqual request.addressOpt - restored.amount shouldEqual request.amount - restored.name shouldEqual request.name - restored.description shouldEqual request.description - restored.decimals shouldEqual request.decimals - } - } - - property("json-encoded dlog secret is always about 32 bytes") { - forAll(dlogSecretWithPublicImageGen) { case (secret, _) => - val wrappedSecret = DlogSecretKey(secret) - val json = wrappedSecret.asJson - json.toString().length shouldBe 66 // 32-bytes hex-encoded data (64 ASCII chars) + quotes == 66 ASCII chars - } - } - - property("dlog secret roundtrip") { - forAll(dlogSecretWithPublicImageGen) { case (secret, _) => - val wrappedSecret = DlogSecretKey(secret) - val json = wrappedSecret.asJson - val parsedSecret = json.as[DlogSecretKey].toOption.get - parsedSecret shouldBe wrappedSecret - } - } - - property("dht secret roundtrip") { - forAll(dhtSecretWithPublicImageGen) { case (secret, _) => - val wrappedSecret = DhtSecretKey(secret) - val json = wrappedSecret.asJson - val parsedSecret = json.as[DhtSecretKey].toOption.get - parsedSecret shouldBe wrappedSecret - } - } - - property("transactionSigningRequest roundtrip") { - forAll(transactionSigningRequestGen(Random.nextBoolean)) { request => - val json = request.asJson - val parsedRequest = json.as[TransactionSigningRequest].toOption.get - parsedRequest shouldBe request - } - } - - property("unsignedErgoTransaction roundtrip") { - forAll(validUnsignedErgoTransactionGen) { case (_, tx) => - val json = tx.asJson - val parsedTx = json.as[UnsignedErgoTransaction].toOption.get - parsedTx shouldBe tx - } - } - - property("PopowProof roundtrip"){ - forAll(poPowProofGen){ pp => - val json = pp.asJson - implicit val decoder: Decoder[NipopowProof] = NipopowProof.nipopowProofDecoder(nipopowAlgos) - val parsedProof = json.as[NipopowProof].toOption.get - parsedProof shouldEqual pp - } - } - - private def checkTrackedBox(c: ACursor, b: TrackedBox)(implicit opts: Detalization) = { - c.downField("spent").as[Boolean] shouldBe Right(b.spendingStatus.spent) - c.downField("onchain").as[Boolean] shouldBe Right(b.chainStatus.onChain) - c.downField("scans").as[Set[ScanId]] shouldBe Right(b.scans) - c.downField("creationOutIndex").as[Short] shouldBe Right(b.creationOutIndex) - c.downField("inclusionHeight").as[Option[Int]] shouldBe Right(b.inclusionHeightOpt) - c.downField("spendingHeight").as[Option[Int]] shouldBe Right(b.spendingHeightOpt) - checkErgoBox(c.downField("box"), b.box) - if (!opts.showDetails) { - c.downField("creationTransactionId").as[String] shouldBe Right(b.creationTxId) - c.downField("spendingTransactionId").as[Option[String]] shouldBe Right(b.spendingTxIdOpt) - } - } - - private def checkErgoBox(c: ACursor, b: ErgoBox): Unit = { - c.downField("boxId").as[String] shouldBe Right(Algos.encode(b.id)) - c.downField("value").as[Long] shouldBe Right(b.value) - c.downField("ergoTree").as[ErgoTree] shouldBe Right(b.ergoTree) - checkAssets(c.downField("assets"), b.additionalTokens.toArray.toSeq) - checkRegisters(c.downField("additionalRegisters"), b.additionalRegisters) - c.downField("creationHeight").as[Int] shouldBe Right(b.creationHeight) - } - - private def checkAssets(c: ACursor, assets: Seq[(ErgoBox.TokenId, Long)]) = { - def stringify(assets: Seq[(ErgoBox.TokenId, Long)]) = { - assets map { case (tokenId, amount) => (Algos.encode(tokenId), amount) } - } - - val Right(decodedAssets) = c.as[Seq[(ErgoBox.TokenId, Long)]] - stringify(decodedAssets) should contain theSameElementsAs stringify(assets) - } - - private def checkRegisters(c: ACursor, registers: AdditionalRegisters) = { - val Right(decodedRegs) = c.as[Map[NonMandatoryRegisterId, EvaluatedValue[SType]]] - decodedRegs should contain theSameElementsAs registers - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala b/ergo-core/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala deleted file mode 100644 index 65ac78905d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala +++ /dev/null @@ -1,124 +0,0 @@ -package org.ergoplatform.serialization - -import org.ergoplatform.modifiers.ErgoNodeViewModifier -import org.ergoplatform.modifiers.history._ -import org.ergoplatform.modifiers.history.extension.ExtensionSerializer -import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.modifiers.history.popow.NipopowProofSerializer -import org.ergoplatform.modifiers.mempool.ErgoTransactionSerializer -import org.ergoplatform.nodeView.history.ErgoSyncInfoSerializer -import org.ergoplatform.nodeView.wallet.persistence.WalletDigestSerializer -import org.ergoplatform.nodeView.state.ErgoStateContextSerializer -import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsSerializer, ErgoValidationSettingsUpdateSerializer} -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.utils.generators.WalletGenerators -import org.scalacheck.Gen -import org.scalatest.Assertion -import scorex.core.serialization.ErgoSerializer - -class SerializationTests extends ErgoPropertyTest with WalletGenerators with scorex.testkit.SerializationTests { - - def checkSerializationRoundtripAndSize[A <: ErgoNodeViewModifier](generator: Gen[A], - serializer: ErgoSerializer[A]): Assertion = { - forAll(generator) { b: A => - val recovered = serializer.parseBytes(serializer.toBytes(b)) - val bytes = serializer.toBytes(b) - bytes shouldEqual serializer.toBytes(recovered) - } - } - - property("Serializers should be defined for all block sections") { - val block = invalidErgoFullBlockGen.sample.get - block.toSeq.foreach { s => - Constants.modifierSerializers.get(s.modifierTypeId) should not be None - } - } - - property("PoPowProof serialization") { - checkSerializationRoundtrip(poPowProofGen, new NipopowProofSerializer(nipopowAlgos)) - } - - property("Header serialization") { - val serializer = HeaderSerializer - forAll(invalidHeaderGen) { b: Header => - val recovered = serializer.parseBytes(serializer.toBytes(b)) - recovered shouldBe b - recovered.size shouldBe serializer.toBytes(b).length - } - } - - property("ErgoStateContext serialization") { - val serializer = ErgoStateContextSerializer(settings) - val b = ergoStateContextGen.sample.get - val recovered = serializer.parseBytes(serializer.toBytes(b)) - serializer.toBytes(b) shouldEqual serializer.toBytes(recovered) - b.lastHeaders.length shouldBe recovered.lastHeaders.length - b.lastHeaders shouldBe recovered.lastHeaders - } - - property("Extension serialization") { - checkSerializationRoundtrip(extensionGen, ExtensionSerializer) - } - - property("ErgoTransactionGen serialization") { - checkSerializationRoundtripAndSize(invalidErgoTransactionGen, ErgoTransactionSerializer) - } - - property("ErgoTransaction .bytes") { - forAll(invalidErgoTransactionGen) { tx => - val bytes = tx.bytes - val txRestored = ErgoTransactionSerializer.parseBytes(bytes) - txRestored.bytes.sameElements(bytes) shouldBe true - } - } - - property("ErgoSyncInfo v1 serialization") { - checkSerializationRoundtrip(ergoSyncInfoV1Gen, ErgoSyncInfoSerializer) - } - - property("ErgoSyncInfo v2 serialization") { - checkSerializationRoundtrip(ergoSyncInfoV2Gen, ErgoSyncInfoSerializer) - } - - property("ErgoHeader serialization") { - checkSerializationRoundtripAndSize(defaultHeaderGen, HeaderSerializer) - } - - property("BlockTransactions serialization") { - checkSerializationRoundtripAndSize(invalidBlockTransactionsGen, BlockTransactionsSerializer) - } - - property("ADProofs serialization") { - checkSerializationRoundtripAndSize(randomADProofsGen, ADProofsSerializer) - } - - property("ModeFeature serialization") { - forAll(modeFeatureGen) { mf => - mf.serializer.parseBytes(mf.serializer.toBytes(mf)) shouldEqual mf - } - } - - property("ErgoValidationSettings serialization") { - val serializer = ErgoValidationSettingsSerializer - forAll(ergoValidationSettingsGen) { vs => - // to bytes / from bytes - serializer.parseBytes(serializer.toBytes(vs)) shouldEqual vs - // to extension / from extension - ErgoValidationSettings.parseExtension(vs.toExtensionCandidate).get shouldEqual vs - } - } - - property("ErgoValidationSettingsUpdate serialization") { - val serializer = ErgoValidationSettingsUpdateSerializer - forAll(ergoValidationSettingsUpdateGen) { vs => - serializer.parseBytes(serializer.toBytes(vs)) shouldEqual vs - } - } - - property("WalletDigest serialization") { - forAll(registrySummaryGen) { index => - WalletDigestSerializer.parseBytes(WalletDigestSerializer.toBytes(index)) shouldEqual index - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala deleted file mode 100644 index e222ec2d88..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala +++ /dev/null @@ -1,178 +0,0 @@ -package org.ergoplatform.settings - -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.settings.RESTApiSettings - -import java.net.{InetSocketAddress, URL} -import scala.concurrent.duration._ - -class ErgoSettingsSpecification extends ErgoPropertyTest { - - private val txCostLimit = initSettings.nodeSettings.maxTransactionCost - private val txSizeLimit = initSettings.nodeSettings.maxTransactionSize - - property("should keep data user home by default") { - val settings = ErgoSettings.read() - settings.directory shouldBe System.getProperty("user.dir") + "/.ergo_test/data" - } - - property("should read default settings") { - val settings = ErgoSettings.read() - settings.nodeSettings shouldBe NodeConfigurationSettings( - StateType.Utxo, - verifyTransactions = true, - 1000, - utxoSettings = UtxoSettings(false, 0, 2), - nipopowSettings = NipopowSettings(false, 1), - mining = true, - txCostLimit, - txSizeLimit, - useExternalMiner = false, - internalMinersCount = 1, - internalMinerPollingInterval = 1.second, - miningPubKeyHex = None, - offlineGeneration = false, - keepVersions = 200, - acceptableChainUpdateDelay = 30.minutes, - mempoolCapacity = 100000, - mempoolCleanupDuration = 10.seconds, - mempoolSorting = SortingOption.FeePerByte, - rebroadcastCount = 3, - minimalFeeAmount = 0, - headerChainDiff = 100, - adProofsSuffixLength = 112*1024, - extraIndex = false - ) - settings.cacheSettings shouldBe CacheSettings( - HistoryCacheSettings( - 12, 1000, 100, 1000 - ), - NetworkCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ), - MempoolCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ) - ) - settings.scorexSettings.restApi shouldBe RESTApiSettings( - bindAddress = new InetSocketAddress("0.0.0.0", 9052), - apiKeyHash = None, - corsAllowedOrigin = Some("*"), - timeout = 5.seconds, - publicUrl = Some(new URL("https://example.com:80")) - ) - } - - property("should read user settings from json file") { - val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.json"), None)) - settings.nodeSettings shouldBe NodeConfigurationSettings( - StateType.Utxo, - verifyTransactions = true, - 12, - utxoSettings = UtxoSettings(false, 0, 2), - nipopowSettings = NipopowSettings(false, 1), - mining = true, - txCostLimit, - txSizeLimit, - useExternalMiner = false, - internalMinersCount = 1, - internalMinerPollingInterval = 1.second, - miningPubKeyHex = None, - offlineGeneration = false, - keepVersions = 200, - acceptableChainUpdateDelay = 30.minutes, - mempoolCapacity = 100000, - mempoolCleanupDuration = 10.seconds, - mempoolSorting = SortingOption.FeePerByte, - rebroadcastCount = 3, - minimalFeeAmount = 0, - headerChainDiff = 100, - adProofsSuffixLength = 112*1024, - extraIndex = false - ) - settings.cacheSettings shouldBe CacheSettings( - HistoryCacheSettings( - 12, 1000, 100, 1000 - ), - NetworkCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ), - MempoolCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ) - ) - } - - property("should read user settings from HOCON file") { - val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.conf"), None)) - settings.nodeSettings shouldBe NodeConfigurationSettings( - StateType.Utxo, - verifyTransactions = true, - 13, - utxoSettings = UtxoSettings(false, 0, 2), - nipopowSettings = NipopowSettings(false, 1), - mining = true, - txCostLimit, - txSizeLimit, - useExternalMiner = false, - internalMinersCount = 1, - internalMinerPollingInterval = 1.second, - miningPubKeyHex = None, - offlineGeneration = false, - keepVersions = 200, - acceptableChainUpdateDelay = 30.minutes, - mempoolCapacity = 100000, - mempoolCleanupDuration = 10.seconds, - mempoolSorting = SortingOption.FeePerByte, - rebroadcastCount = 3, - minimalFeeAmount = 0, - headerChainDiff = 100, - adProofsSuffixLength = 112*1024, - extraIndex = false - ) - settings.cacheSettings shouldBe CacheSettings( - HistoryCacheSettings( - 12, 1000, 100, 1000 - ), - NetworkCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ), - MempoolCacheSettings( - invalidModifiersCacheSize = 10000, - invalidModifiersCacheExpiration = 6.hours, - ) - ) - } - - property("scorex.restApi.publicUrl should be valid") { - val invalidUrls = - List( - "http:invalid", - "http://localhost", - "http://127.0.0.1", - "http://0.0.0.0", - "http://example.com/foo/bar", - "http://example.com?foo=bar" - ).map(new URL(_)) - - invalidUrls.forall(ErgoSettings.invalidRestApiUrl) shouldBe true - - val validUrls = - List( - "http://example.com", - "http://example.com:80", - "http://82.90.21.31", - "http://82.90.21.31:80" - ).map(new URL(_)) - - validUrls.forall(url => !ErgoSettings.invalidRestApiUrl(url)) shouldBe true - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala b/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala deleted file mode 100644 index 2923aa7b31..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/settings/VotingSpecification.scala +++ /dev/null @@ -1,351 +0,0 @@ -package org.ergoplatform.settings - -import org.ergoplatform.modifiers.history.extension.ExtensionCandidate -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.state.{ErgoStateContext, VotingData} -import org.ergoplatform.settings.ValidationRules.rulesSpec -import org.ergoplatform.utils.ErgoPropertyTest -import org.ergoplatform.validation.{DisabledRule, ReplacedRule, ValidationRules => VR} -import scorex.crypto.authds.ADDigest - -import scala.util.Try - -class VotingSpecification extends ErgoPropertyTest { - - import Parameters._ - - private val headerId = scorex.util.bytesToId(Array.fill(32)(0: Byte)) - - private val votingEpochLength = 2 - - private val hfActivationHeight = 100 - - private val hfActivationDifficultyHex = "01" - - override implicit val votingSettings: VotingSettings = - VotingSettings( - votingEpochLength, - softForkEpochs = 2, - activationEpochs = 3, - version2ActivationHeight = hfActivationHeight, - version2ActivationDifficultyHex = hfActivationDifficultyHex - ) - - private val updSettings = settings.copy(chainSettings = settings.chainSettings.copy(voting = votingSettings)) - - private val proposedUpdate = ErgoValidationSettingsUpdate( - Seq(ValidationRules.exDuplicateKeys, ValidationRules.exValueLength), - Seq(VR.CheckDeserializedScriptType.id -> DisabledRule, VR.CheckValidOpCode.id -> ReplacedRule((VR.FirstRuleId + 11).toShort))) - private val proposedUpdate2 = ErgoValidationSettingsUpdate(Seq(ValidationRules.fbOperationFailed), Seq()) - val ctx: ErgoStateContext = { - new ErgoStateContext(Seq.empty, None, genesisStateDigest, parameters, validationSettingsNoIl, VotingData.empty)(updSettings) - .upcoming(org.ergoplatform.mining.group.generator, 0L, settings.chainSettings.initialNBits, Array.fill(3)(0.toByte), emptyVSUpdate, 0.toByte) - } - val initialVs: ErgoValidationSettings = ctx.validationSettings - val extensionWithAllParams: ExtensionCandidate = { - parameters.toExtensionCandidate ++ initialVs.toExtensionCandidate - } - - val emptyParameters = Parameters(0, Map.empty, ErgoValidationSettingsUpdate.empty) - - property("correct rule ids") { - rulesSpec foreach { r => - r._1 < org.ergoplatform.validation.ValidationRules.FirstRuleId shouldBe true - } - } - - property("ErgoValidationSettings toExtension/fromExtension roundtrip") { - // initial settings should not be written into Extension at all - val initial = ErgoValidationSettings.initial - val extension = initial.toExtensionCandidate - extension.fields.size shouldBe 0 - initial shouldBe ErgoValidationSettings.parseExtension(extension).get - - forAll(ergoValidationSettingsGen) { vs => - val extension = vs.toExtensionCandidate - vs shouldBe ErgoValidationSettings.parseExtension(extension).get - } - } - - property("Parameters should be defined at the beginning of the epoch") { - val chain = genChain(votingEpochLength * 4).map { b => - if (b.header.votingStarts(votingEpochLength)) { - b.copy(extension = extensionWithAllParams.toExtension(b.header.id)) - } else { - b - } - } - val validChain = chain.init - val lastBlock = chain.last - val invalidExtBlock1 = { // extension does not contain all required params - lastBlock.copy(extension = lastBlock.extension.copy( - fields = Seq(Array(0: Byte, 1: Byte) -> Array.fill(4)(2: Byte))) - ) - } - val invalidExtBlock2 = { // extension contains redundant parameter - lastBlock.copy(extension = lastBlock.extension.copy( - fields = parameters.toExtensionCandidate.fields :+ Array(0: Byte, 99: Byte) -> Array.fill(4)(2: Byte)) - ) - } - val invalidExtBlock3 = { // extension does not contain params at all - lastBlock.copy(extension = lastBlock.extension.copy(fields = Seq())) - } - val validCtx = validChain.foldLeft(ctx)((acc, mod) => acc.appendFullBlock(mod).get) - validCtx.appendFullBlock(invalidExtBlock1) shouldBe 'failure - validCtx.appendFullBlock(invalidExtBlock2) shouldBe 'failure - validCtx.appendFullBlock(invalidExtBlock3) shouldBe 'failure - validCtx.appendFullBlock(lastBlock) shouldBe 'success - } - - property("voting for non-existing parameter") { - val p: Parameters = Parameters(2, Map(BlockVersion -> 0), proposedUpdate) - val vr: VotingData = VotingData.empty - val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings) - val invalidVote = 100: Byte - val votes = Array(invalidVote , NoParameter, NoParameter) - - // voting for non-existing param is okay if not start of an epoch - val h = defaultHeaderGen.sample.get.copy(height = 1, votes = votes, version = 0: Byte) - val esc2 = esc.appendHeader(h).get - - // proposing a vote for non-existing param is not allowed - val h2 = defaultHeaderGen.sample.get.copy(height = 2, votes = votes, version = 0: Byte) - esc2.appendHeader(h2).toEither.left.get.getMessage.contains("Incorrect vote") shouldBe true - } - - //Simple checks for votes in header could be found also in NonVerifyADHistorySpecification("Header votes") - property("simple voting - start - conditions") { - val kInit = 1000000 - - val p: Parameters = Parameters(2, Map(StorageFeeFactorIncrease -> kInit, BlockVersion -> 0), proposedUpdate) - val vr: VotingData = VotingData.empty - val esc = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings) - val votes = Array(StorageFeeFactorIncrease, NoParameter, NoParameter) - val h = defaultHeaderGen.sample.get.copy(height = 2, votes = votes, version = 0: Byte) - val esc2 = process(esc, p, h).get - - //no quorum gathered - no parameter change - val he = defaultHeaderGen.sample.get.copy(votes = Array.fill(3)(NoParameter), version = 0: Byte) - val esc30 = process(esc2, p, he).get - val esc40 = process(esc30, p, he).get - esc40.currentParameters.storageFeeFactor shouldBe kInit - - //quorum gathered - parameter change - val esc31 = process(esc2, p, h.copy(height = 3)).get - esc31.votingData.epochVotes.find(_._1 == StorageFeeFactorIncrease).get._2 shouldBe 2 - - val p4 = Parameters(4, Map(StorageFeeFactorIncrease -> (kInit + Parameters.StorageFeeFactorStep), BlockVersion -> 0), proposedUpdate) - val esc41 = process(esc31, p4, he.copy(height = 4)).get - esc41.currentParameters.storageFeeFactor shouldBe (kInit + Parameters.StorageFeeFactorStep) - } - - /** - * A test which is ensuring that approved soft-fork activates properly. - * For the test, we have: - * - epoch length is about 2 blocks - * - 2 epochs to vote - * - 3 epochs to activate the fork - * - * So the fork would be activated only if 4 votes out of 4 are for it. - */ - property("soft fork - w. activation") { - - val p: Parameters = Parameters(1, Map(BlockVersion -> 0), proposedUpdate) - val vr: VotingData = VotingData.empty - val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettings, vr)(updSettings) - checkValidationSettings(esc0.validationSettings, emptyVSUpdate) - val forkVote = Array(SoftFork, NoParameter, NoParameter) - val emptyVotes = Array(NoParameter, NoParameter, NoParameter) - - val h1 = defaultHeaderGen.sample.get.copy(height = 1) - val esc1 = process(esc0, p, h1).get - - // Soft-fork vote is proposed @ height == 2 - val h2 = defaultHeaderGen.sample.get.copy(votes = forkVote, version = 0: Byte, height = 2) - val expectedParameters2 = Parameters(2, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 0, BlockVersion -> 0), proposedUpdate) - val esc2 = process(esc1, expectedParameters2, h2).get - esc2.currentParameters.softForkStartingHeight.get shouldBe 2 - esc2.currentParameters.proposedUpdate shouldBe proposedUpdate - checkValidationSettings(esc2.validationSettings, emptyVSUpdate) - - // voting for the fork @ height == 3 - val h3 = h2.copy(height = 3) - - val expectedParameters3 = Parameters(2, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 1, BlockVersion -> 0), proposedUpdate) - val esc3 = process(esc2, expectedParameters3, h3).get - esc3.currentParameters.softForkStartingHeight.get shouldBe 2 - esc3.currentParameters.proposedUpdate shouldBe proposedUpdate - checkValidationSettings(esc3.validationSettings, emptyVSUpdate) - - // voting for the fork @ height == 4 - // new epoch is starting, thus the block should contain number of votes for the fork collected in the previous epoch - val h4 = h3.copy(height = 4) - val expectedParameters4 = Parameters(4, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 2, BlockVersion -> 0), proposedUpdate) - val esc4 = process(esc3, expectedParameters4, h4).get - - esc4.currentParameters.softForkStartingHeight.get shouldBe 2 - esc4.currentParameters.softForkVotesCollected.get shouldBe 2 - esc4.currentParameters.proposedUpdate shouldBe proposedUpdate - checkValidationSettings(esc4.validationSettings, emptyVSUpdate) - - // voting for the fork @ height == 5 - val h5 = h4.copy(height = 5) - val expectedParameters5 = Parameters(4, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 3, BlockVersion -> 0), proposedUpdate) - val esc5 = process(esc4, expectedParameters5, h5).get - checkValidationSettings(esc5.validationSettings, emptyVSUpdate) - - // voting is finished, and we check collected votes @ height == 6 - val h6 = h5.copy(height = 6, votes = emptyVotes) - val expectedParameters6 = Parameters(6, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 4, BlockVersion -> 0), proposedUpdate) - val esc6 = process(esc5, expectedParameters6, h6).get - checkValidationSettings(esc5.validationSettings, emptyVSUpdate) - - // voting for soft-fork is prohibited @ height == 6 - val h6w = h5.copy(height = 6) - process(esc5, expectedParameters6, h6w).isFailure shouldBe true - - val esc11 = (7 to 11).foldLeft(esc6) { case (esc, i) => - // voting for soft-fork is prohibited during activation period - val hw = h6.copy(height = i, votes = forkVote) - process(esc, expectedParameters6, hw).isFailure shouldBe true - - val h = h6.copy(height = i) - - process(esc, expectedParameters6, h).get - } - - // activation period done @ height = 12, block version is increased, rules to disable are disabled - val h12 = h6.copy(height = 12, version = 1: Byte) - val expectedParameters12 = Parameters(12, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 4, BlockVersion -> 1), proposedUpdate) - - val esc12 = process(esc11, expectedParameters12, h12).get - checkValidationSettings(esc12.validationSettings, proposedUpdate) - - // vote for soft-fork @ activation height - val h12w = h12.copy(votes = forkVote) - process(esc11, expectedParameters12, h12w).isFailure shouldBe true - - val h13 = h12.copy(height = 13) - val esc13 = process(esc12, expectedParameters12, h13).get - - // vote for soft-fork is prohibited before next epoch after activation height - val h13w = h13.copy(votes = forkVote) - process(esc12, expectedParameters12, h13w).isFailure shouldBe true - - // voting for soft-fork is possible on the first block of the next epoch after activation height - val h14 = h13.copy(height = 14, votes = forkVote) - val expectedParameters14 = Parameters(14, Map(SoftForkStartingHeight -> 14, SoftForkVotesCollected -> 0, BlockVersion -> 1), proposedUpdate2) - val esc14 = process(esc13, expectedParameters14, h14).get - checkValidationSettings(esc14.validationSettings, proposedUpdate) - - // next epoch after activation height - soft-fork related parameters are cleared - val h14b = h13.copy(height = 14, votes = emptyVotes) - val expectedParameters14a = Parameters(14, Map(BlockVersion -> 1), proposedUpdate2) - process(esc13, expectedParameters14a, h14b).get - checkValidationSettings(esc14.validationSettings, proposedUpdate) - } - - /** - * A vote for a soft-fork which is not gathering enough votes to be activated. - * The voting settings are : - * - epoch length is about 2 blocks - * - 2 epochs to vote - * - 3 epochs to activate the fork - * - */ - property("soft fork - unsuccessful voting") { - val p: Parameters = Parameters(1, Map(BlockVersion -> 0), proposedUpdate) - val vr: VotingData = VotingData.empty - val forkVote = Array(SoftFork, NoParameter, NoParameter) - val emptyVotes = Array(NoParameter, NoParameter, NoParameter) - - val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), p, validationSettingsNoIl, vr)(updSettings) - val h1 = defaultHeaderGen.sample.get.copy(votes = forkVote, version = 0: Byte, height = 1) - val esc1 = process(esc0, p, h1).get - - // Soft-fork vote is proposed @ height == 2 - val h2 = defaultHeaderGen.sample.get.copy(votes = forkVote, version = 0: Byte, height = 2) - val expectedParameters2 = Parameters(2, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 0, BlockVersion -> 0), proposedUpdate) - val esc2 = process(esc1, expectedParameters2, h2).get - esc2.currentParameters.softForkStartingHeight.get shouldBe 2 - - // voting for the fork @ height == 3 - val h3 = h2.copy(height = 3) - val expectedParameters3 = Parameters(2, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 1, BlockVersion -> 0), proposedUpdate) - val esc3 = process(esc2, expectedParameters3, h3).get - esc3.currentParameters.softForkStartingHeight.get shouldBe 2 - - // voting for the fork @ height == 4 - val h4 = h3.copy(height = 4) - val expectedParameters4 = Parameters(4, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 2, BlockVersion -> 0), proposedUpdate) - val esc4 = process(esc3, expectedParameters4, h4).get - esc4.currentParameters.softForkStartingHeight.get shouldBe 2 - esc4.currentParameters.softForkVotesCollected.get shouldBe 2 - - // no vote for the fork @ height == 5, so only soft-fork proposal has gathered 75% only - val h5 = h4.copy(height = 5, votes = emptyVotes) - val expectedParameters5 = Parameters(4, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 3, BlockVersion -> 0), proposedUpdate) - val esc5 = process(esc4, expectedParameters5, h5).get - - // first epoch after the voting done, data should still be in the block - val h6 = h5.copy(height = 6) - val expectedParameters6 = Parameters(6, Map(SoftForkStartingHeight -> 2, SoftForkVotesCollected -> 3, BlockVersion -> 0), proposedUpdate) - val esc6 = process(esc5, expectedParameters6, h6).get - - // in the first epoch after the voting done, it is prohibited to propose a new voting for a fork - val h6w = h5.copy(height = 6, votes = forkVote) - process(esc5, expectedParameters6, h6w).isFailure shouldBe true - - val h7 = h6.copy(height = 7) - val esc7 = process(esc6, expectedParameters6, h7).get - - //... also prohibited to vote for a fork during the first epoch after the voting done - val h7w = h6.copy(height = 7, votes = forkVote) - process(esc6, expectedParameters6, h7w).isFailure shouldBe true - - // a new fork voting is proposed on the first block of the second epoch after voting (which has not gathered enough) - val h8 = h7.copy(height = 8, votes = forkVote) - val expectedParameters8 = Parameters(8, Map(SoftForkStartingHeight -> 8, SoftForkVotesCollected -> 0, BlockVersion -> 0), proposedUpdate) - process(esc7, expectedParameters8, h8).get - - // on the second epoch after voting (not old enough) parameters are to be cleared, - // and block version to be the same - val h8e = h7.copy(height = 8, votes = emptyVotes) - val expectedParameters8e = Parameters(8, Map(BlockVersion -> 0), proposedUpdate) - process(esc7, expectedParameters8e, h8e).get - } - - property("hardfork - v2 - activation") { - val vr: VotingData = VotingData.empty - val esc0 = new ErgoStateContext(Seq(), None, ADDigest @@ Array.fill(33)(0: Byte), parameters, ErgoValidationSettings.initial, vr)(updSettings) - val h1 = defaultHeaderGen.sample.get.copy(votes = Array.empty, version = 1: Byte, height = hfActivationHeight - 1) - val expectedParameters1 = Parameters(hfActivationHeight - 1, DefaultParameters, ErgoValidationSettingsUpdate.empty) - val esc1 = process(esc0, expectedParameters1, h1).get - val h2 = defaultHeaderGen.sample.get.copy(votes = Array.empty, version = 2: Byte, height = hfActivationHeight) - val expectedParameters2 = Parameters(hfActivationHeight, DefaultParameters.updated(BlockVersion, 2: Byte), ErgoValidationSettingsUpdate.empty) - val esc2 = process(esc1, expectedParameters2, h2).get - esc2.currentParameters.blockVersion shouldBe 2 - } - - private def checkValidationSettings(vs: ErgoValidationSettings, updated: ErgoValidationSettingsUpdate): Unit = { - vs.rules.foreach { r => - vs.isActive(r._1) shouldBe !updated.rulesToDisable.contains(r._1) - } - updated.statusUpdates.foreach { su => - vs.sigmaSettings.getStatus(su._1).get shouldBe su._2 - } - } - - private def process(esc: ErgoStateContext, - expectedParameters: Parameters, - header: Header): Try[ErgoStateContext] = { - val upcoming = esc.upcoming(header.minerPk, header.timestamp, header.nBits, header.votes, expectedParameters.proposedUpdate, header.version) - val calculatedParams = upcoming.currentParameters - expectedParameters.parametersTable.foreach { case (paramId, paramValue) => - calculatedParams.parametersTable(paramId) shouldBe paramValue - } - val extension = (upcoming.currentParameters.toExtensionCandidate ++ upcoming.validationSettings.toExtensionCandidate).toExtension(headerId) - esc.process(header, Some(extension)) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala deleted file mode 100644 index 7fb07b62f9..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala +++ /dev/null @@ -1,221 +0,0 @@ -package org.ergoplatform.tools - -import org.ergoplatform._ -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.mining.{AutolykosPowScheme, CandidateBlock, CandidateGenerator} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.history.ErgoHistory.Height -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.settings._ -import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers} -import org.ergoplatform.wallet.boxes.{BoxSelector, ReplaceCompactCollectBoxSelector} -import scorex.util.ModifierId -import sigmastate.crypto.DLogProtocol.ProveDlog - -import java.io.File -import scala.annotation.tailrec -import scala.concurrent.duration._ -import scala.util.Try - -/** - * Application object for chain generation. - * Takes 2 parameters: start timestamp and path to history folder. - * Generate blocks starting from start timestamp and until current time with expected block interval - * between them, to ensure that difficulty does not change. - */ -object ChainGenerator extends App with ErgoTestHelpers { - - val realNetworkSetting = { - val initSettings = ErgoSettings.read(Args(None, Some(NetworkType.TestNet))) - initSettings.copy(chainSettings = initSettings.chainSettings.copy(genesisId = None)) - } - - val EmissionTxCost: Long = 20000 - val MinTxAmount: Long = 2000000 - val RewardDelay: Int = realNetworkSetting.chainSettings.monetary.minerRewardDelay - val MaxTxsPerBlock: Int = 10 - - val prover = defaultProver - val minerPk = prover.hdKeys.head.publicImage - val selfAddressScript = P2PKAddress(minerPk).script - val minerProp = ErgoTreePredef.rewardOutputScript(RewardDelay, minerPk) - - val pow = new AutolykosPowScheme(powScheme.k, powScheme.n) - val blockInterval = 2.minute - - val boxSelector: BoxSelector = new ReplaceCompactCollectBoxSelector(30, 2, None) - - val startTime = args.headOption.map(_.toLong).getOrElse(System.currentTimeMillis() - (blockInterval * 10).toMillis) - val dir = if (args.length < 2) new File("/tmp/ergo/data") else new File(args(1)) - val txsSize: Int = if (args.length < 3) 100 * 1024 else args(2).toInt - - val minimalSuffix = 2 - val txCostLimit = initSettings.nodeSettings.maxTransactionCost - val txSizeLimit = initSettings.nodeSettings.maxTransactionSize - val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(StateType.Utxo, verifyTransactions = true, - -1, UtxoSettings(false, 0, 2), NipopowSettings(false, 1), mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, - internalMinersCount = 1, internalMinerPollingInterval = 1.second, miningPubKeyHex = None, offlineGeneration = false, - 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, rebroadcastCount = 20, - 1000000, 100, adProofsSuffixLength = 112*1024, extraIndex = false) - val ms = settings.chainSettings.monetary.copy( - minerRewardDelay = RewardDelay - ) - val cs = realNetworkSetting.chainSettings - - val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, cs, - nodeSettings, settings.scorexSettings, settings.walletSettings, settings.cacheSettings) - val stateDir = ErgoState.stateDir(fullHistorySettings) - stateDir.mkdirs() - - val votingEpochLength = votingSettings.votingLength - val protocolVersion = fullHistorySettings.chainSettings.protocolVersion - - val history = ErgoHistory.readOrGenerate(fullHistorySettings)(context = null) - HistoryTestHelpers.allowToApplyOldBlocks(history) - val (state, _) = ErgoState.generateGenesisUtxoState(stateDir, fullHistorySettings) - log.info(s"Going to generate a chain at ${dir.getAbsoluteFile} starting from ${history.bestFullBlockOpt}") - - val chain = loop(state, None, None, Seq()) - log.info(s"Chain of length ${chain.length} generated") - history.bestHeaderOpt shouldBe history.bestFullBlockOpt.map(_.header) - history.bestFullBlockOpt.get.id shouldBe chain.last - log.info("History was generated successfully") - System.exit(0) - - private def loop(state: UtxoState, - initBox: Option[ErgoBox], - last: Option[Header], - acc: Seq[ModifierId]): Seq[ModifierId] = { - val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime) - if (time < System.currentTimeMillis()) { - val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight), - initBox, state.stateContext) - - val candidate = genCandidate(prover.hdPubKeys.head.key, last, time, txs, state) - val block = proveCandidate(candidate.get) - - history.append(block.header).get - block.blockSections.foreach(s => if (!history.contains(s)) history.append(s).get) - - val outToPassNext = if (last.isEmpty) { - block.transactions.flatMap(_.outputs).find(_.ergoTree == minerProp) - } else { - lastOut - } - - assert(outToPassNext.isDefined) - - log.info( - s"Block ${block.id} with ${block.transactions.size} transactions at height ${block.header.height} generated") - - loop(state.applyModifier(block, None)(_ => ()).get, outToPassNext, Some(block.header), acc :+ block.id) - } else { - acc - } - } - - private def genTransactions(height: Height, - inOpt: Option[ErgoBox], - ctx: ErgoStateContext): (Seq[ErgoTransaction], Option[ErgoBox]) = { - inOpt - .find { bx => - val canUnlock = (bx.creationHeight + RewardDelay <= height) || (bx.ergoTree != minerProp) - canUnlock && bx.ergoTree != cs.monetary.emissionBoxProposition && bx.value >= MinTxAmount - } - .map { input => - val qty = MaxTxsPerBlock - val amount = input.value - val outs = (0 until qty).map(_ => new ErgoBoxCandidate(amount, selfAddressScript, height)) - val x = outs - .foldLeft((Seq.empty[ErgoTransaction], input)) { case ((acc, in), out) => - val inputs = IndexedSeq(in) - val unsignedTx = UnsignedErgoTransaction( - inputs.map(_.id).map(id => new UnsignedInput(id)), - IndexedSeq(out) - ) - - prover.sign(unsignedTx, inputs, emptyDataBoxes, ctx) - .fold(_ => acc -> in, tx => (acc :+ ErgoTransaction(tx)) -> unsignedTx.outputs.head) - } - ._1 - (x, Some(x.last.outputs.head)) - } - .getOrElse(Seq.empty -> inOpt) - } - - private def genCandidate(minerPk: ProveDlog, - lastHeaderOpt: Option[Header], - ts: Long, - txsFromPool: Seq[ErgoTransaction], - state: UtxoStateReader): Try[CandidateBlock] = Try { - val stateContext = state.stateContext - val nBits: Long = lastHeaderOpt - .map(parent => history.requiredDifficultyAfter(parent)) - .map(d => DifficultySerializer.encodeCompactBits(d)) - .getOrElse(settings.chainSettings.initialNBits) - - val interlinks = lastHeaderOpt - .flatMap { h => - history.typedModifierById[Extension](h.extensionId) - .flatMap(ext => NipopowAlgos.unpackInterlinks(ext.fields).toOption) - .map(nipopowAlgos.updateInterlinks(h, _)) - } - .getOrElse(Seq.empty) - val interlinksExtension = nipopowAlgos.interlinksToExtension(interlinks) - - val (extensionCandidate, votes: Array[Byte], version: Byte) = lastHeaderOpt.map { header => - val newHeight = header.height + 1 - val currentParams = stateContext.currentParameters - val betterVersion = protocolVersion > header.version - val votingFinishHeight: Option[Height] = currentParams.softForkStartingHeight - .map(_ + votingSettings.votingLength * votingSettings.softForkEpochs) - val forkVotingAllowed = votingFinishHeight.forall(fh => newHeight < fh) - val forkOrdered = settings.votingTargets.softFork != 0 - val voteForFork = betterVersion && forkOrdered && forkVotingAllowed - - if (newHeight % votingEpochLength == 0 && newHeight > 0) { - val (newParams, _) = currentParams.update(newHeight, voteForFork, stateContext.votingData.epochVotes, emptyVSUpdate, votingSettings) - (newParams.toExtensionCandidate ++ interlinksExtension, - newParams.suggestVotes(settings.votingTargets.targets, voteForFork), - newParams.blockVersion) - } else { - (nipopowAlgos.interlinksToExtension(interlinks), - currentParams.vote(settings.votingTargets.targets, stateContext.votingData.epochVotes, voteForFork), - currentParams.blockVersion) - } - }.getOrElse((interlinksExtension, Array(0: Byte, 0: Byte, 0: Byte), Header.InitialVersion)) - - val emissionTxOpt = CandidateGenerator.collectEmission(state, minerPk, emptyStateContext) - val txs = emissionTxOpt.toSeq ++ txsFromPool - - state.proofsForTransactions(txs).map { case (adProof, adDigest) => - CandidateBlock(lastHeaderOpt, version, nBits, adDigest, adProof, txs, ts, extensionCandidate, votes) - } - }.flatten - - @tailrec - private def proveCandidate(candidate: CandidateBlock): ErgoFullBlock = { - log.info(s"Trying to prove block with parent ${candidate.parentOpt.map(_.encodedId)} and timestamp ${candidate.timestamp}") - - pow.proveCandidate(candidate, prover.hdKeys.head.privateInput.w) match { - case Some(fb) => fb - case _ => - val interlinks = candidate.parentOpt - .map(nipopowAlgos.updateInterlinks(_, NipopowAlgos.unpackInterlinks(candidate.extension.fields).get)) - .getOrElse(Seq.empty) - val minerTag = scorex.utils.Random.randomBytes(Extension.FieldKeySize) - proveCandidate { - candidate.copy( - extension = ExtensionCandidate(Seq(Array(0: Byte, 2: Byte) -> minerTag)) ++ nipopowAlgos.interlinksToExtension(interlinks) - ) - } - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/ConfigGenerator.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/ConfigGenerator.scala deleted file mode 100644 index 2ba172a4ad..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/ConfigGenerator.scala +++ /dev/null @@ -1,55 +0,0 @@ -package org.ergoplatform.tools - -import java.io.{File, PrintWriter} - -import org.ergoplatform.utils.ErgoTestHelpers -import org.ergoplatform.wallet.mnemonic.Mnemonic -import org.ergoplatform.wallet.interface4j.SecretString - -object ConfigGenerator extends App with ErgoTestHelpers { - - val seedStrength = 128 - - val qty = args(0).toInt - val apiKeyHash = args(1) - val digestMode = if (args(2) == "true") true else false - val mining = if (args(3) == "true") !digestMode else false - val saveDirPath = if (args.length < 5) "/tmp/ergo/configs" else args(4) - - (0 to qty).foreach { i => - val stateType = if (digestMode) "digest" else "utxo" - val cfgName = s"node-$stateType-$i-local.conf" - val nodeName = s"node-$stateType-$i-devnet" - val mnemonic = genMnemonic - dumpToFile(saveDirPath, cfgName, template(digestMode, mining, mnemonic, apiKeyHash, nodeName)) - } - - private def dumpToFile(dir: String, cfgName: String, content: String): Unit = { - new File(dir).mkdirs() - val outWriter = new PrintWriter(new File(s"$dir/$cfgName")) - outWriter.write(content) - outWriter.close() - } - - private def template(digestMode: Boolean, mining: Boolean, - mnemonic: SecretString, apiKeyHash: String, nodeName: String): String = - s""" - |ergo.node.stateType = "${if (digestMode) "digest" else "utxo"}" - |ergo.node.mining = ${if (mining) "true" else "false"} - |ergo.node.offlineGeneration = true - |ergo.node.useExternalMiner = false - |ergo.testing.transactionGeneration = true - |ergo.wallet.testMnemonic = "$mnemonic" - |ergo.wallet.testKeysQty = 10 - |scorex.restApi.apiKeyHash = "$apiKeyHash" - |scorex.network.nodeName = "$nodeName" - """.stripMargin - - private def genMnemonic = { - val entropy = scorex.utils.Random.randomBytes(seedStrength / 8) - new Mnemonic(settings.walletSettings.mnemonicPhraseLanguage, settings.walletSettings.seedStrengthBits) - .toMnemonic(entropy) - .get - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/DefaultParametersPrinter.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/DefaultParametersPrinter.scala deleted file mode 100644 index 05bee3973a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/DefaultParametersPrinter.scala +++ /dev/null @@ -1,26 +0,0 @@ -package org.ergoplatform.tools - -import org.ergoplatform.settings.LaunchParameters.parametersTable -import org.ergoplatform.settings.Parameters.{maxValues, minValues, parametersDescs, stepsTable} - -object DefaultParametersPrinter extends App { - lazy val parametersDescription: String = { - """ - |\begin{tabular}{*{6}{l}} - |Id & Description & Default & Step & Min & Max \\ - |\hline - """.stripMargin + - parametersDescs.toSeq.sortBy(_._1).map { case (id, desc) => - val defaultOpt = parametersTable.get(id) - val stepOpt = stepsTable.get(id) - val minValue = minValues.get(id) - val maxValue = maxValues.get(id) - s"$id & $desc & ${defaultOpt.getOrElse("-")} & ${stepOpt.getOrElse("-")} & ${minValue.getOrElse("-")} & ${maxValue.getOrElse("-")} \\\\" - }.mkString("\n") + - """ - |\end{tabular} - """.stripMargin - } - - print(parametersDescription) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala deleted file mode 100644 index 8c38a167e4..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala +++ /dev/null @@ -1,162 +0,0 @@ -package org.ergoplatform.tools - -import org.ergoplatform.mining.difficulty.{DifficultyAdjustment, DifficultySerializer} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty -import org.ergoplatform.settings.ErgoSettings -import org.ergoplatform.utils.generators.ErgoGenerators - -import scala.annotation.tailrec -import scala.collection.mutable -import scala.concurrent.duration._ -import scala.io.Source -import scala.util.Random - -/** - * Object that allows to simulate blockchain with the specified difficulty control function and estimate deviation - * of block interval from the desired one - */ -object DifficultyControlSimulator extends App with ErgoGenerators { - - val baseHeader = defaultHeaderGen.sample.get - // val difficultyControl = new LinearDifficultyControl(1.minute, useLastEpochs = 100, epochLength = 1) - val epochLength = 256 - val chainSettings = settings.chainSettings.copy(blockInterval = 2.minute, useLastEpochs = 8, epochLength = epochLength) - val difficultyControl = new DifficultyAdjustment(chainSettings) - // Constant rate: Stable simulated average interval = 119713, error = 0.23916666% | Init simulated average interval = 117794, error = 1.8383334% - // Increasing rate: Stable simulated average interval = 119841, error = 0.1325% | Init simulated average interval = 119077, error = 0.76916665% - // Random rate: Stable simulated average interval = 120539, error = 0.44916666% | Init simulated average interval = 115519, error = 3.7341666% - - blockchainSimulator(difficultyControl, - baseHeader.copy(height = 0, timestamp = 0, nBits = 16842752), - randomHashRate) - - /** - * Generate blockchain starting from initial header with specified difficulty control and measure mean time interval between blocks - * - * @param difficultyControl - * @param initialHeader - */ - def blockchainSimulator(difficultyControl: DifficultyAdjustment, - initialHeader: Header, - timeForOneHash: Int => Int): Unit = { - // number of blocks in simulated chain - val chainLength = 100000 - - val curChain = mutable.Map[Int, Header](initialHeader.height -> initialHeader) - - @tailrec - def genchain(curHeight: Int): mutable.Map[Int, Header] = { - - if (curHeight >= chainLength) { - curChain - } else { - val lastHeader = curChain(curHeight) - val requiredDifficulty = requiredDifficultyAfter(lastHeader, curChain) - val target = 1.toDouble / requiredDifficulty.toDouble - - val hashTime = timeForOneHash(curHeight) - - @tailrec - def simulateTimeDiff(currentDiff: Long = 0): Long = { - val hit = Random.nextDouble() - if (hit < target) { - currentDiff + hashTime - } else { - simulateTimeDiff(currentDiff + hashTime) - } - } - - val timeDiff = simulateTimeDiff() - val newHeader = lastHeader.copy(timestamp = lastHeader.timestamp + timeDiff, - height = curHeight + 1, - nBits = DifficultySerializer.encodeCompactBits(requiredDifficulty)) - curChain(newHeader.height) = newHeader - - genchain(curHeight + 1) - } - } - - val chain = genchain(initialHeader.height) - - printEpochs(chain.values.toSeq.sortBy(_.height), difficultyControl) - - - } - - def printTestnetData(): Unit = { - val baseHeader = defaultHeaderGen.sample.get - val chainSettings = ErgoSettings.read().chainSettings.copy(epochLength = 1) - val difficultyControl = new DifficultyAdjustment(chainSettings) - - val headers = Source.fromResource("difficulty.csv").getLines().toSeq.tail.map { line => - val l = line.split(",") - baseHeader.copy( - height = l(0).toInt, - timestamp = l(1).toLong, - nBits = DifficultySerializer.encodeCompactBits(BigInt(l(2))) - ) - } - printEpochs(headers, difficultyControl) - } - - def printEpochs(headers: Seq[Header], difficultyControl: DifficultyAdjustment): Unit = { - case class Epoch(startHeight: Int, requiredDifficulty: BigInt, blockInterval: FiniteDuration, timestamp: Long) { - val realDifficulty: BigInt = requiredDifficulty * difficultyControl.desiredInterval.toMillis / blockInterval.toMillis - - override def toString: String = s"$startHeight,$requiredDifficulty,$realDifficulty,${blockInterval.toMillis}" - } - - val epochs: Seq[Epoch] = headers.filter(h => h.height % epochLength == 0).sliding(2).map { p => - val start = p.head - val end = p.last - val meanInterval = ((end.timestamp - start.timestamp) / (end.height - start.height)).millis - - Epoch(start.height, end.requiredDifficulty, meanInterval, end.timestamp) - }.toSeq - - val initEpochs: Seq[Epoch] = epochs.take(difficultyControl.useLastEpochs).tail - val stableEpochs: Seq[Epoch] = epochs.drop(difficultyControl.useLastEpochs) - val simulatedInit = initEpochs.map(_.blockInterval.toMillis).sum / initEpochs.length - val simulatedStable = stableEpochs.map(_.blockInterval.toMillis).sum / stableEpochs.length - val desired = difficultyControl.desiredInterval.toMillis - val errorInit = Math.abs(simulatedInit - desired).toFloat * 100 / desired - val errorStable = Math.abs(simulatedStable - desired).toFloat * 100 / desired - - println(s"Control:") - println(s"Desired interval = $desired, epoch length = $epochLength, use last epochs = " + - difficultyControl.useLastEpochs) - println(s"Init simulated average interval = $simulatedInit, error = $errorInit%") - println(s"Stable simulated average interval = $simulatedStable, error = $errorStable%") - - /* - println(s"height,requiredDifficulty,realDifficulty,timeDiff") - epochs.foreach(d => println(d)) -*/ - } - - - private def requiredDifficultyAfter(parent: Header, blockchain: mutable.Map[Int, Header]): Difficulty = { - val parentHeight = parent.height - val heights = difficultyControl.previousHeightsRequiredForRecalculation(parentHeight + 1, epochLength) - .ensuring(_.last == parentHeight) - if (heights.lengthCompare(1) == 0) { - difficultyControl.calculate(Seq(parent), epochLength) - } else { - val headersToCalculate = heights.map(h => blockchain(h)) - difficultyControl.calculate(headersToCalculate, epochLength) - } - } - - - def constantHashRate(height: Int): Int = { - 1000 - } - - def linearGrowingHashRate(height: Int): Int = Math.max(2000 - height / 20, 100) - - def randomHashRate(height: Int): Int = { - Random.nextInt(1000) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala deleted file mode 100644 index 9eebe3f4b7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/FeeSimulator.scala +++ /dev/null @@ -1,105 +0,0 @@ -package org.ergoplatform.tools - -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.settings.Constants._ -import org.ergoplatform.settings.LaunchParameters._ -import org.ergoplatform.{ErgoBoxCandidate, Input} -import scorex.crypto.authds.ADKey -import scorex.utils.Random -import sigma.Colls -import sigmastate.crypto.DLogProtocol.DLogProverInput -import sigmastate.eval.Extensions.ArrayByteOps -import sigmastate.eval._ -import sigmastate.interpreter.{ContextExtension, ProverResult} - - -object FeeSimulator extends App { - - //Block size is 500Kb - private val BlockSize = 500 * 1024 - - val k1 = DLogProverInput.random().publicImage - val k2 = DLogProverInput.random().publicImage - - val input = Input(ADKey @@ Random.randomBytes(32), ProverResult(Random.randomBytes(65), ContextExtension(Map()))) - val creationHeight: Int = 100000 - - val box1 = new ErgoBoxCandidate( - scala.util.Random.nextLong(), k1, creationHeight, - Colls.fromItems(Random.randomBytes(32).toTokenId -> scala.util.Random.nextLong())) - val box2 = new ErgoBoxCandidate(scala.util.Random.nextLong(), k2, creationHeight) - - val simpleTx = ErgoTransaction(IndexedSeq(input, input), IndexedSeq(box1, box2)) - val stdSize = simpleTx.outputs.map(_.bytes.length).sum / simpleTx.outputs.length - val simpleTxSize = simpleTx.size - val outputsSize = simpleTx.outputs.map(_.bytes.length).sum - lazy val perOutputFee = stdSize * storageFeeFactor / CoinsInOneErgo.toDouble - val minStdDust = minValuePerByte * stdSize - val byteFeeBitcoin = 0.00039128734 * CoinsInOneErgo - - println("=====================") - println("Global parameters:") - println(s"Storage fee factor: $storageFeeFactor") - println(s"Output size: $stdSize B") - println(s"Simple tx size: $simpleTxSize B") - println(s"Block size: $BlockSize B") - println(s"Storage fee for ordinary output: $perOutputFee") - println(s"Min dust value of standard-size box: $minStdDust") - - println("=====================") - println(s"Assume that Ergo state has the same number of outputs($bitcoinUtxos), as Bitcoin.") - - def bitcoinUtxos = 60000000 - - println(s"Reward per block: ${perOutputFee * (bitcoinUtxos.toDouble / StoragePeriod)} Erg + tx fees") - - - println("=====================") - println(s"Assume that blocks are full and miner is requiring upfront payment equal to storage fee to move a box") - - println(s"Reward per block: ${BlockSize * storageFeeFactor / CoinsInOneErgo.toDouble} Erg") - - val minTxFee = storageFeeFactor * outputsSize / CoinsInOneErgo.toDouble - println(s"Tx fee: $minTxFee") - - println(s"Everyday relocation: ${minTxFee * StoragePeriod / BlocksPerDay}") - println(s"Weekly relocation: ${minTxFee * StoragePeriod / BlocksPerWeek}") - println(s"Monthly relocation: ${minTxFee * StoragePeriod / BlocksPerMonth}") - println(s"Yearly relocation: ${minTxFee * StoragePeriod / BlocksPerYear}") - - println("=====================") - println("Assume tx byte in Ergo has the same USD cost as in Bitcoin") - - //(not very realistic, as we take current market price of Ergo token, but it will be much higher probably under the assumption of equality) - val blockFee = maxBlockSize * byteFeeBitcoin - println(s"Reward per block: ${blockFee / CoinsInOneErgo.toDouble} Erg") - println(s"bytefee Bitcoin: ${byteFeeBitcoin / CoinsInOneErgo.toDouble} Erg") - - - println("=====================") - println("Assume that a miner is requiring minimum tx fee proportional to lifetime of its inputs and average" + - " box lifetime equals to Bitcoin (8182 blocks)") - - // Mean lifetime of a box in Bitcoin = 8182 blocks. - val LBitcoin = 8182 - - val meanMinTxFee = outputsSize * storageFeeFactor * LBitcoin / StoragePeriod.toDouble - - println(s"Reward per block: ${BlockSize * storageFeeFactor * LBitcoin / StoragePeriod.toDouble / CoinsInOneErgo.toDouble} Erg") - - println(s"Tx fee: ${meanMinTxFee / CoinsInOneErgo.toDouble}") - - println("=====================") - println("Assume that a miner is requiring minimum tx fee proportional to lifetime of its inputs and average" + - " box lifetime equals to Bitcoin (56,8 days)") - - // Mean lifetime of a box in Ergo = 56,8 days - val LErgo = LBitcoin * 5 - - val meanMinTxFeeE = outputsSize * storageFeeFactor * LErgo / StoragePeriod.toDouble - - println(s"Reward per block: ${BlockSize * storageFeeFactor * LErgo / StoragePeriod.toDouble / CoinsInOneErgo.toDouble} Erg") - - println(s"Tx fee: ${meanMinTxFeeE / CoinsInOneErgo.toDouble}") - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/MinerBench.scala b/ergo-core/src/test/scala/org/ergoplatform/tools/MinerBench.scala deleted file mode 100644 index 7a997bfb05..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/MinerBench.scala +++ /dev/null @@ -1,90 +0,0 @@ -package org.ergoplatform.tools - -import com.google.common.primitives.Bytes -import org.bouncycastle.util.BigIntegers -import org.ergoplatform.mining._ -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.modifiers.history.extension.ExtensionCandidate -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.utils.ErgoTestHelpers -import scorex.crypto.hash.{Blake2b256, Blake2b512, CryptographicHash, Digest} - -import scala.annotation.tailrec - -object MinerBench extends App with ErgoTestHelpers { - - validationBench() - // numericHashBench() - - def numericHashBench(): Unit = { - val Steps = 100000000 - - def numericHash(hf: CryptographicHash[_ <: Digest], validRange: BigInt): Unit = { - @tailrec - def hash(input: Array[Byte]): BigInt = { - val hashed = hf.apply(input) - val bi = BigInt(BigIntegers.fromUnsignedByteArray(hashed)) - if (bi < validRange) { - bi.mod(q) - } else { - log.debug(s"Calculate one more hash for ${encoder.encode(input)} and p=$q") - hash(hashed) - } - } - } - - val data = Bytes.concat(Array.fill(16486)(1.toByte)) - // test Blake2b256 - val validRange256: BigInt = (BigInt(2).pow(Blake2b256.DigestSize * 8) / q) * q - - // prepare JVM - (0 until Steps).foreach(_ => numericHash(Blake2b256, validRange256)) - - val st = System.currentTimeMillis() - (0 until Steps).foreach(_ => numericHash(Blake2b256, validRange256)) - val st2 = System.currentTimeMillis() - - val validRange512: BigInt = (BigInt(2).pow(Blake2b512.DigestSize * 8) / q) * q - - // prepare JVM - (0 until Steps).foreach(_ => numericHash(Blake2b512, validRange512)) - - val st3 = System.currentTimeMillis() - (0 until Steps).foreach(_ => numericHash(Blake2b512, validRange512)) - val st4 = System.currentTimeMillis() - - println(s"Calculation time of $Steps numberic hashes over ${data.length} bytes") - println(s"Blake2b256: ${st2 - st} ms") - println(s"Blake2b512: ${st4 - st3} ms") - - } - - def validationBench() { - val pow = new AutolykosPowScheme(powScheme.k, powScheme.n) - val sk = randomSecret() - val difficulty = 1000 - val fb = invalidErgoFullBlockGen.sample.get - val inHeader = fb.header - val nBits = DifficultySerializer.encodeCompactBits(difficulty) - val h = inHeader.copy(nBits = nBits) - - val candidate = new CandidateBlock(None, Header.InitialVersion, nBits: Long, h.stateRoot, - fb.adProofs.get.proofBytes, - fb.blockTransactions.txs, - System.currentTimeMillis(), - ExtensionCandidate(Seq.empty), - Array()) - val newHeader = pow.proveCandidate(candidate, sk).get.header - - val Steps = 10000 - - (0 until Steps / 10) foreach (_ => pow.validate(newHeader)) - - val st = System.currentTimeMillis() - - (0 until Steps) foreach (_ => pow.validate(newHeader)) - - println(s"M = ${pow.M.length / 1024} Kb:${(System.currentTimeMillis() - st).toDouble / Steps} ms") - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/emission.csv b/ergo-core/src/test/scala/org/ergoplatform/tools/emission.csv deleted file mode 100644 index 19515a1926..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/emission.csv +++ /dev/null @@ -1,1169 +0,0 @@ -age (years), total coins, current rate -0.0, 0, 75.0 -0.00684931506849315, 135000, 75.0 -0.0136986301369863, 270000, 75.0 -0.02054794520547945, 405000, 75.0 -0.0273972602739726, 540000, 75.0 -0.03424657534246575, 675000, 75.0 -0.0410958904109589, 810000, 75.0 -0.04794520547945205, 945000, 75.0 -0.0547945205479452, 1080000, 75.0 -0.06164383561643835, 1215000, 75.0 -0.0684931506849315, 1350000, 75.0 -0.07534246575342465, 1485000, 75.0 -0.0821917808219178, 1620000, 75.0 -0.08904109589041095, 1755000, 75.0 -0.0958904109589041, 1890000, 75.0 -0.10273972602739725, 2025000, 75.0 -0.1095890410958904, 2160000, 75.0 -0.11643835616438356, 2295000, 75.0 -0.1232876712328767, 2430000, 75.0 -0.13013698630136986, 2565000, 75.0 -0.136986301369863, 2700000, 75.0 -0.14383561643835616, 2835000, 75.0 -0.1506849315068493, 2970000, 75.0 -0.15753424657534246, 3105000, 75.0 -0.1643835616438356, 3240000, 75.0 -0.17123287671232876, 3375000, 75.0 -0.1780821917808219, 3510000, 75.0 -0.18493150684931506, 3645000, 75.0 -0.1917808219178082, 3780000, 75.0 -0.19863013698630136, 3915000, 75.0 -0.2054794520547945, 4050000, 75.0 -0.21232876712328766, 4185000, 75.0 -0.2191780821917808, 4320000, 75.0 -0.22602739726027396, 4455000, 75.0 -0.2328767123287671, 4590000, 75.0 -0.23972602739726026, 4725000, 75.0 -0.2465753424657534, 4860000, 75.0 -0.2534246575342466, 4995000, 75.0 -0.2602739726027397, 5130000, 75.0 -0.2671232876712329, 5265000, 75.0 -0.273972602739726, 5400000, 75.0 -0.2808219178082192, 5535000, 75.0 -0.2876712328767123, 5670000, 75.0 -0.2945205479452055, 5805000, 75.0 -0.3013698630136986, 5940000, 75.0 -0.3082191780821918, 6075000, 75.0 -0.3150684931506849, 6210000, 75.0 -0.3219178082191781, 6345000, 75.0 -0.3287671232876712, 6480000, 75.0 -0.3356164383561644, 6615000, 75.0 -0.3424657534246575, 6750000, 75.0 -0.3493150684931507, 6885000, 75.0 -0.3561643835616438, 7020000, 75.0 -0.363013698630137, 7155000, 75.0 -0.3698630136986301, 7290000, 75.0 -0.3767123287671233, 7425000, 75.0 -0.3835616438356164, 7560000, 75.0 -0.3904109589041096, 7695000, 75.0 -0.3972602739726027, 7830000, 75.0 -0.4041095890410959, 7965000, 75.0 -0.410958904109589, 8100000, 75.0 -0.4178082191780822, 8235000, 75.0 -0.4246575342465753, 8370000, 75.0 -0.4315068493150685, 8505000, 75.0 -0.4383561643835616, 8640000, 75.0 -0.4452054794520548, 8775000, 75.0 -0.4520547945205479, 8910000, 75.0 -0.4589041095890411, 9045000, 75.0 -0.4657534246575342, 9180000, 75.0 -0.4726027397260274, 9315000, 75.0 -0.4794520547945205, 9450000, 75.0 -0.4863013698630137, 9585000, 75.0 -0.4931506849315068, 9720000, 75.0 -0.5, 9855000, 75.0 -0.5068493150684932, 9990000, 75.0 -0.5136986301369864, 10125000, 75.0 -0.5205479452054794, 10260000, 75.0 -0.5273972602739726, 10395000, 75.0 -0.5342465753424658, 10530000, 75.0 -0.541095890410959, 10665000, 75.0 -0.547945205479452, 10800000, 75.0 -0.5547945205479452, 10935000, 75.0 -0.5616438356164384, 11070000, 75.0 -0.5684931506849316, 11205000, 75.0 -0.5753424657534246, 11340000, 75.0 -0.5821917808219178, 11475000, 75.0 -0.589041095890411, 11610000, 75.0 -0.5958904109589042, 11745000, 75.0 -0.6027397260273972, 11880000, 75.0 -0.6095890410958904, 12015000, 75.0 -0.6164383561643836, 12150000, 75.0 -0.6232876712328768, 12285000, 75.0 -0.6301369863013698, 12420000, 75.0 -0.636986301369863, 12555000, 75.0 -0.6438356164383562, 12690000, 75.0 -0.6506849315068494, 12825000, 75.0 -0.6575342465753424, 12960000, 75.0 -0.6643835616438356, 13095000, 75.0 -0.6712328767123288, 13230000, 75.0 -0.678082191780822, 13365000, 75.0 -0.684931506849315, 13500000, 75.0 -0.6917808219178082, 13635000, 75.0 -0.6986301369863014, 13770000, 75.0 -0.7054794520547946, 13905000, 75.0 -0.7123287671232876, 14040000, 75.0 -0.7191780821917808, 14175000, 75.0 -0.726027397260274, 14310000, 75.0 -0.7328767123287672, 14445000, 75.0 -0.7397260273972602, 14580000, 75.0 -0.7465753424657534, 14715000, 75.0 -0.7534246575342466, 14850000, 75.0 -0.7602739726027398, 14985000, 75.0 -0.7671232876712328, 15120000, 75.0 -0.773972602739726, 15255000, 75.0 -0.7808219178082192, 15390000, 75.0 -0.7876712328767124, 15525000, 75.0 -0.7945205479452054, 15660000, 75.0 -0.8013698630136986, 15795000, 75.0 -0.8082191780821918, 15930000, 75.0 -0.815068493150685, 16065000, 75.0 -0.821917808219178, 16200000, 75.0 -0.8287671232876712, 16335000, 75.0 -0.8356164383561644, 16470000, 75.0 -0.8424657534246576, 16605000, 75.0 -0.8493150684931506, 16740000, 75.0 -0.8561643835616438, 16875000, 75.0 -0.863013698630137, 17010000, 75.0 -0.8698630136986302, 17145000, 75.0 -0.8767123287671232, 17280000, 75.0 -0.8835616438356164, 17415000, 75.0 -0.8904109589041096, 17550000, 75.0 -0.8972602739726028, 17685000, 75.0 -0.9041095890410958, 17820000, 75.0 -0.910958904109589, 17955000, 75.0 -0.9178082191780822, 18090000, 75.0 -0.9246575342465754, 18225000, 75.0 -0.9315068493150684, 18360000, 75.0 -0.9383561643835616, 18495000, 75.0 -0.9452054794520548, 18630000, 75.0 -0.952054794520548, 18765000, 75.0 -0.958904109589041, 18900000, 75.0 -0.9657534246575342, 19035000, 75.0 -0.9726027397260274, 19170000, 75.0 -0.9794520547945206, 19305000, 75.0 -0.9863013698630136, 19440000, 75.0 -0.9931506849315068, 19575000, 75.0 -1.0, 19710000, 75.0 -1.0068493150684932, 19845000, 75.0 -1.0136986301369864, 19980000, 75.0 -1.0205479452054795, 20115000, 75.0 -1.0273972602739727, 20250000, 75.0 -1.0342465753424657, 20385000, 75.0 -1.0410958904109588, 20520000, 75.0 -1.047945205479452, 20655000, 75.0 -1.0547945205479452, 20790000, 75.0 -1.0616438356164384, 20925000, 75.0 -1.0684931506849316, 21060000, 75.0 -1.0753424657534247, 21195000, 75.0 -1.082191780821918, 21330000, 75.0 -1.0890410958904109, 21465000, 75.0 -1.095890410958904, 21600000, 75.0 -1.1027397260273972, 21735000, 75.0 -1.1095890410958904, 21870000, 75.0 -1.1164383561643836, 22005000, 75.0 -1.1232876712328768, 22140000, 75.0 -1.13013698630137, 22275000, 75.0 -1.1369863013698631, 22410000, 75.0 -1.143835616438356, 22545000, 75.0 -1.1506849315068493, 22680000, 75.0 -1.1575342465753424, 22815000, 75.0 -1.1643835616438356, 22950000, 75.0 -1.1712328767123288, 23085000, 75.0 -1.178082191780822, 23220000, 75.0 -1.1849315068493151, 23355000, 75.0 -1.1917808219178083, 23490000, 75.0 -1.1986301369863013, 23625000, 75.0 -1.2054794520547945, 23760000, 75.0 -1.2123287671232876, 23895000, 75.0 -1.2191780821917808, 24030000, 75.0 -1.226027397260274, 24165000, 75.0 -1.2328767123287672, 24300000, 75.0 -1.2397260273972603, 24435000, 75.0 -1.2465753424657535, 24570000, 75.0 -1.2534246575342465, 24705000, 75.0 -1.2602739726027397, 24840000, 75.0 -1.2671232876712328, 24975000, 75.0 -1.273972602739726, 25110000, 75.0 -1.2808219178082192, 25245000, 75.0 -1.2876712328767124, 25380000, 75.0 -1.2945205479452055, 25515000, 75.0 -1.3013698630136987, 25650000, 75.0 -1.3082191780821917, 25785000, 75.0 -1.3150684931506849, 25920000, 75.0 -1.321917808219178, 26055000, 75.0 -1.3287671232876712, 26190000, 75.0 -1.3356164383561644, 26325000, 75.0 -1.3424657534246576, 26460000, 75.0 -1.3493150684931507, 26595000, 75.0 -1.356164383561644, 26730000, 75.0 -1.3630136986301369, 26865000, 75.0 -1.36986301369863, 27000000, 75.0 -1.3767123287671232, 27135000, 75.0 -1.3835616438356164, 27270000, 75.0 -1.3904109589041096, 27405000, 75.0 -1.3972602739726028, 27540000, 75.0 -1.404109589041096, 27675000, 75.0 -1.4109589041095891, 27810000, 75.0 -1.417808219178082, 27945000, 75.0 -1.4246575342465753, 28080000, 75.0 -1.4315068493150684, 28215000, 75.0 -1.4383561643835616, 28350000, 75.0 -1.4452054794520548, 28485000, 75.0 -1.452054794520548, 28620000, 75.0 -1.4589041095890412, 28755000, 75.0 -1.4657534246575343, 28890000, 75.0 -1.4726027397260273, 29025000, 75.0 -1.4794520547945205, 29160000, 75.0 -1.4863013698630136, 29295000, 75.0 -1.4931506849315068, 29430000, 75.0 -1.5, 29565000, 75.0 -1.5068493150684932, 29700000, 75.0 -1.5136986301369864, 29835000, 75.0 -1.5205479452054795, 29970000, 75.0 -1.5273972602739727, 30105000, 75.0 -1.5342465753424657, 30240000, 75.0 -1.5410958904109588, 30375000, 75.0 -1.547945205479452, 30510000, 75.0 -1.5547945205479452, 30645000, 75.0 -1.5616438356164384, 30780000, 75.0 -1.5684931506849316, 30915000, 75.0 -1.5753424657534247, 31050000, 75.0 -1.582191780821918, 31185000, 75.0 -1.5890410958904109, 31320000, 75.0 -1.595890410958904, 31455000, 75.0 -1.6027397260273972, 31590000, 75.0 -1.6095890410958904, 31725000, 75.0 -1.6164383561643836, 31860000, 75.0 -1.6232876712328768, 31995000, 75.0 -1.63013698630137, 32130000, 75.0 -1.6369863013698631, 32265000, 75.0 -1.643835616438356, 32400000, 75.0 -1.6506849315068493, 32535000, 75.0 -1.6575342465753424, 32670000, 75.0 -1.6643835616438356, 32805000, 75.0 -1.6712328767123288, 32940000, 75.0 -1.678082191780822, 33075000, 75.0 -1.6849315068493151, 33210000, 75.0 -1.6917808219178083, 33345000, 75.0 -1.6986301369863013, 33480000, 75.0 -1.7054794520547945, 33615000, 75.0 -1.7123287671232876, 33750000, 75.0 -1.7191780821917808, 33885000, 75.0 -1.726027397260274, 34020000, 75.0 -1.7328767123287672, 34155000, 75.0 -1.7397260273972603, 34290000, 75.0 -1.7465753424657535, 34425000, 75.0 -1.7534246575342465, 34560000, 75.0 -1.7602739726027397, 34695000, 75.0 -1.7671232876712328, 34830000, 75.0 -1.773972602739726, 34965000, 75.0 -1.7808219178082192, 35100000, 75.0 -1.7876712328767124, 35235000, 75.0 -1.7945205479452055, 35370000, 75.0 -1.8013698630136987, 35505000, 75.0 -1.8082191780821917, 35640000, 75.0 -1.8150684931506849, 35775000, 75.0 -1.821917808219178, 35910000, 75.0 -1.8287671232876712, 36045000, 75.0 -1.8356164383561644, 36180000, 75.0 -1.8424657534246576, 36315000, 75.0 -1.8493150684931507, 36450000, 75.0 -1.856164383561644, 36585000, 75.0 -1.8630136986301369, 36720000, 75.0 -1.86986301369863, 36855000, 75.0 -1.8767123287671232, 36990000, 75.0 -1.8835616438356164, 37125000, 75.0 -1.8904109589041096, 37260000, 75.0 -1.8972602739726028, 37395000, 75.0 -1.904109589041096, 37530000, 75.0 -1.9109589041095891, 37665000, 75.0 -1.917808219178082, 37800000, 75.0 -1.9246575342465753, 37935000, 75.0 -1.9315068493150684, 38070000, 75.0 -1.9383561643835616, 38205000, 75.0 -1.9452054794520548, 38340000, 75.0 -1.952054794520548, 38475000, 75.0 -1.9589041095890412, 38610000, 75.0 -1.9657534246575343, 38745000, 75.0 -1.9726027397260273, 38880000, 75.0 -1.9794520547945205, 39015000, 75.0 -1.9863013698630136, 39150000, 75.0 -1.9931506849315068, 39285000, 75.0 -2.0, 39420000, 72.0 -2.006849315068493, 39549600, 72.0 -2.0136986301369864, 39679200, 72.0 -2.0205479452054793, 39808800, 72.0 -2.0273972602739727, 39938400, 72.0 -2.0342465753424657, 40068000, 72.0 -2.041095890410959, 40197600, 72.0 -2.047945205479452, 40327200, 72.0 -2.0547945205479454, 40456800, 72.0 -2.0616438356164384, 40586400, 72.0 -2.0684931506849313, 40716000, 72.0 -2.0753424657534247, 40845600, 72.0 -2.0821917808219177, 40975200, 72.0 -2.089041095890411, 41104800, 72.0 -2.095890410958904, 41234400, 72.0 -2.1027397260273974, 41364000, 72.0 -2.1095890410958904, 41493600, 72.0 -2.1164383561643834, 41623200, 72.0 -2.1232876712328768, 41752800, 72.0 -2.1301369863013697, 41882400, 72.0 -2.136986301369863, 42012000, 72.0 -2.143835616438356, 42141600, 72.0 -2.1506849315068495, 42271200, 72.0 -2.1575342465753424, 42400800, 72.0 -2.164383561643836, 42530400, 72.0 -2.171232876712329, 42660000, 72.0 -2.1780821917808217, 42789600, 72.0 -2.184931506849315, 42919200, 72.0 -2.191780821917808, 43048800, 72.0 -2.1986301369863015, 43178400, 72.0 -2.2054794520547945, 43308000, 72.0 -2.212328767123288, 43437600, 72.0 -2.219178082191781, 43567200, 72.0 -2.2260273972602738, 43696800, 72.0 -2.232876712328767, 43826400, 72.0 -2.23972602739726, 43956000, 72.0 -2.2465753424657535, 44085600, 69.0 -2.2534246575342465, 44209800, 69.0 -2.26027397260274, 44334000, 69.0 -2.267123287671233, 44458200, 69.0 -2.2739726027397262, 44582400, 69.0 -2.280821917808219, 44706600, 69.0 -2.287671232876712, 44830800, 69.0 -2.2945205479452055, 44955000, 69.0 -2.3013698630136985, 45079200, 69.0 -2.308219178082192, 45203400, 69.0 -2.315068493150685, 45327600, 69.0 -2.3219178082191783, 45451800, 69.0 -2.328767123287671, 45576000, 69.0 -2.335616438356164, 45700200, 69.0 -2.3424657534246576, 45824400, 69.0 -2.3493150684931505, 45948600, 69.0 -2.356164383561644, 46072800, 69.0 -2.363013698630137, 46197000, 69.0 -2.3698630136986303, 46321200, 69.0 -2.3767123287671232, 46445400, 69.0 -2.3835616438356166, 46569600, 69.0 -2.3904109589041096, 46693800, 69.0 -2.3972602739726026, 46818000, 69.0 -2.404109589041096, 46942200, 69.0 -2.410958904109589, 47066400, 69.0 -2.4178082191780823, 47190600, 69.0 -2.4246575342465753, 47314800, 69.0 -2.4315068493150687, 47439000, 69.0 -2.4383561643835616, 47563200, 69.0 -2.4452054794520546, 47687400, 69.0 -2.452054794520548, 47811600, 69.0 -2.458904109589041, 47935800, 69.0 -2.4657534246575343, 48060000, 69.0 -2.4726027397260273, 48184200, 69.0 -2.4794520547945207, 48308400, 69.0 -2.4863013698630136, 48432600, 69.0 -2.493150684931507, 48556800, 66.0 -2.5, 48675600, 66.0 -2.506849315068493, 48794400, 66.0 -2.5136986301369864, 48913200, 66.0 -2.5205479452054793, 49032000, 66.0 -2.5273972602739727, 49150800, 66.0 -2.5342465753424657, 49269600, 66.0 -2.541095890410959, 49388400, 66.0 -2.547945205479452, 49507200, 66.0 -2.5547945205479454, 49626000, 66.0 -2.5616438356164384, 49744800, 66.0 -2.5684931506849313, 49863600, 66.0 -2.5753424657534247, 49982400, 66.0 -2.5821917808219177, 50101200, 66.0 -2.589041095890411, 50220000, 66.0 -2.595890410958904, 50338800, 66.0 -2.6027397260273974, 50457600, 66.0 -2.6095890410958904, 50576400, 66.0 -2.6164383561643834, 50695200, 66.0 -2.6232876712328768, 50814000, 66.0 -2.6301369863013697, 50932800, 66.0 -2.636986301369863, 51051600, 66.0 -2.643835616438356, 51170400, 66.0 -2.6506849315068495, 51289200, 66.0 -2.6575342465753424, 51408000, 66.0 -2.664383561643836, 51526800, 66.0 -2.671232876712329, 51645600, 66.0 -2.6780821917808217, 51764400, 66.0 -2.684931506849315, 51883200, 66.0 -2.691780821917808, 52002000, 66.0 -2.6986301369863015, 52120800, 66.0 -2.7054794520547945, 52239600, 66.0 -2.712328767123288, 52358400, 66.0 -2.719178082191781, 52477200, 66.0 -2.7260273972602738, 52596000, 66.0 -2.732876712328767, 52714800, 66.0 -2.73972602739726, 52833600, 63.0 -2.7465753424657535, 52947000, 63.0 -2.7534246575342465, 53060400, 63.0 -2.76027397260274, 53173800, 63.0 -2.767123287671233, 53287200, 63.0 -2.7739726027397262, 53400600, 63.0 -2.780821917808219, 53514000, 63.0 -2.787671232876712, 53627400, 63.0 -2.7945205479452055, 53740800, 63.0 -2.8013698630136985, 53854200, 63.0 -2.808219178082192, 53967600, 63.0 -2.815068493150685, 54081000, 63.0 -2.8219178082191783, 54194400, 63.0 -2.828767123287671, 54307800, 63.0 -2.835616438356164, 54421200, 63.0 -2.8424657534246576, 54534600, 63.0 -2.8493150684931505, 54648000, 63.0 -2.856164383561644, 54761400, 63.0 -2.863013698630137, 54874800, 63.0 -2.8698630136986303, 54988200, 63.0 -2.8767123287671232, 55101600, 63.0 -2.8835616438356166, 55215000, 63.0 -2.8904109589041096, 55328400, 63.0 -2.8972602739726026, 55441800, 63.0 -2.904109589041096, 55555200, 63.0 -2.910958904109589, 55668600, 63.0 -2.9178082191780823, 55782000, 63.0 -2.9246575342465753, 55895400, 63.0 -2.9315068493150687, 56008800, 63.0 -2.9383561643835616, 56122200, 63.0 -2.9452054794520546, 56235600, 63.0 -2.952054794520548, 56349000, 63.0 -2.958904109589041, 56462400, 63.0 -2.9657534246575343, 56575800, 63.0 -2.9726027397260273, 56689200, 63.0 -2.9794520547945207, 56802600, 63.0 -2.9863013698630136, 56916000, 60.0 -2.993150684931507, 57024000, 60.0 -3.0, 57132000, 60.0 -3.006849315068493, 57240000, 60.0 -3.0136986301369864, 57348000, 60.0 -3.0205479452054793, 57456000, 60.0 -3.0273972602739727, 57564000, 60.0 -3.0342465753424657, 57672000, 60.0 -3.041095890410959, 57780000, 60.0 -3.047945205479452, 57888000, 60.0 -3.0547945205479454, 57996000, 60.0 -3.0616438356164384, 58104000, 60.0 -3.0684931506849313, 58212000, 60.0 -3.0753424657534247, 58320000, 60.0 -3.0821917808219177, 58428000, 60.0 -3.089041095890411, 58536000, 60.0 -3.095890410958904, 58644000, 60.0 -3.1027397260273974, 58752000, 60.0 -3.1095890410958904, 58860000, 60.0 -3.1164383561643834, 58968000, 60.0 -3.1232876712328768, 59076000, 60.0 -3.1301369863013697, 59184000, 60.0 -3.136986301369863, 59292000, 60.0 -3.143835616438356, 59400000, 60.0 -3.1506849315068495, 59508000, 60.0 -3.1575342465753424, 59616000, 60.0 -3.164383561643836, 59724000, 60.0 -3.171232876712329, 59832000, 60.0 -3.1780821917808217, 59940000, 60.0 -3.184931506849315, 60048000, 60.0 -3.191780821917808, 60156000, 60.0 -3.1986301369863015, 60264000, 60.0 -3.2054794520547945, 60372000, 60.0 -3.212328767123288, 60480000, 60.0 -3.219178082191781, 60588000, 60.0 -3.2260273972602738, 60696000, 60.0 -3.232876712328767, 60804000, 57.0 -3.23972602739726, 60906600, 57.0 -3.2465753424657535, 61009200, 57.0 -3.2534246575342465, 61111800, 57.0 -3.26027397260274, 61214400, 57.0 -3.267123287671233, 61317000, 57.0 -3.2739726027397262, 61419600, 57.0 -3.280821917808219, 61522200, 57.0 -3.287671232876712, 61624800, 57.0 -3.2945205479452055, 61727400, 57.0 -3.3013698630136985, 61830000, 57.0 -3.308219178082192, 61932600, 57.0 -3.315068493150685, 62035200, 57.0 -3.3219178082191783, 62137800, 57.0 -3.328767123287671, 62240400, 57.0 -3.335616438356164, 62343000, 57.0 -3.3424657534246576, 62445600, 57.0 -3.3493150684931505, 62548200, 57.0 -3.356164383561644, 62650800, 57.0 -3.363013698630137, 62753400, 57.0 -3.3698630136986303, 62856000, 57.0 -3.3767123287671232, 62958600, 57.0 -3.3835616438356166, 63061200, 57.0 -3.3904109589041096, 63163800, 57.0 -3.3972602739726026, 63266400, 57.0 -3.404109589041096, 63369000, 57.0 -3.410958904109589, 63471600, 57.0 -3.4178082191780823, 63574200, 57.0 -3.4246575342465753, 63676800, 57.0 -3.4315068493150687, 63779400, 57.0 -3.4383561643835616, 63882000, 57.0 -3.4452054794520546, 63984600, 57.0 -3.452054794520548, 64087200, 57.0 -3.458904109589041, 64189800, 57.0 -3.4657534246575343, 64292400, 57.0 -3.4726027397260273, 64395000, 57.0 -3.4794520547945207, 64497600, 54.0 -3.4863013698630136, 64594800, 54.0 -3.493150684931507, 64692000, 54.0 -3.5, 64789200, 54.0 -3.506849315068493, 64886400, 54.0 -3.5136986301369864, 64983600, 54.0 -3.5205479452054793, 65080800, 54.0 -3.5273972602739727, 65178000, 54.0 -3.5342465753424657, 65275200, 54.0 -3.541095890410959, 65372400, 54.0 -3.547945205479452, 65469600, 54.0 -3.5547945205479454, 65566800, 54.0 -3.5616438356164384, 65664000, 54.0 -3.5684931506849313, 65761200, 54.0 -3.5753424657534247, 65858400, 54.0 -3.5821917808219177, 65955600, 54.0 -3.589041095890411, 66052800, 54.0 -3.595890410958904, 66150000, 54.0 -3.6027397260273974, 66247200, 54.0 -3.6095890410958904, 66344400, 54.0 -3.6164383561643834, 66441600, 54.0 -3.6232876712328768, 66538800, 54.0 -3.6301369863013697, 66636000, 54.0 -3.636986301369863, 66733200, 54.0 -3.643835616438356, 66830400, 54.0 -3.6506849315068495, 66927600, 54.0 -3.6575342465753424, 67024800, 54.0 -3.664383561643836, 67122000, 54.0 -3.671232876712329, 67219200, 54.0 -3.6780821917808217, 67316400, 54.0 -3.684931506849315, 67413600, 54.0 -3.691780821917808, 67510800, 54.0 -3.6986301369863015, 67608000, 54.0 -3.7054794520547945, 67705200, 54.0 -3.712328767123288, 67802400, 54.0 -3.719178082191781, 67899600, 54.0 -3.7260273972602738, 67996800, 51.0 -3.732876712328767, 68088600, 51.0 -3.73972602739726, 68180400, 51.0 -3.7465753424657535, 68272200, 51.0 -3.7534246575342465, 68364000, 51.0 -3.76027397260274, 68455800, 51.0 -3.767123287671233, 68547600, 51.0 -3.7739726027397262, 68639400, 51.0 -3.780821917808219, 68731200, 51.0 -3.787671232876712, 68823000, 51.0 -3.7945205479452055, 68914800, 51.0 -3.8013698630136985, 69006600, 51.0 -3.808219178082192, 69098400, 51.0 -3.815068493150685, 69190200, 51.0 -3.8219178082191783, 69282000, 51.0 -3.828767123287671, 69373800, 51.0 -3.835616438356164, 69465600, 51.0 -3.8424657534246576, 69557400, 51.0 -3.8493150684931505, 69649200, 51.0 -3.856164383561644, 69741000, 51.0 -3.863013698630137, 69832800, 51.0 -3.8698630136986303, 69924600, 51.0 -3.8767123287671232, 70016400, 51.0 -3.8835616438356166, 70108200, 51.0 -3.8904109589041096, 70200000, 51.0 -3.8972602739726026, 70291800, 51.0 -3.904109589041096, 70383600, 51.0 -3.910958904109589, 70475400, 51.0 -3.9178082191780823, 70567200, 51.0 -3.9246575342465753, 70659000, 51.0 -3.9315068493150687, 70750800, 51.0 -3.9383561643835616, 70842600, 51.0 -3.9452054794520546, 70934400, 51.0 -3.952054794520548, 71026200, 51.0 -3.958904109589041, 71118000, 51.0 -3.9657534246575343, 71209800, 51.0 -3.9726027397260273, 71301600, 48.0 -3.9794520547945207, 71388000, 48.0 -3.9863013698630136, 71474400, 48.0 -3.993150684931507, 71560800, 48.0 -4.0, 71647200, 48.0 -4.006849315068493, 71733600, 48.0 -4.013698630136986, 71820000, 48.0 -4.02054794520548, 71906400, 48.0 -4.027397260273973, 71992800, 48.0 -4.034246575342466, 72079200, 48.0 -4.041095890410959, 72165600, 48.0 -4.0479452054794525, 72252000, 48.0 -4.054794520547945, 72338400, 48.0 -4.061643835616438, 72424800, 48.0 -4.068493150684931, 72511200, 48.0 -4.075342465753424, 72597600, 48.0 -4.082191780821918, 72684000, 48.0 -4.089041095890411, 72770400, 48.0 -4.095890410958904, 72856800, 48.0 -4.102739726027397, 72943200, 48.0 -4.109589041095891, 73029600, 48.0 -4.116438356164384, 73116000, 48.0 -4.123287671232877, 73202400, 48.0 -4.13013698630137, 73288800, 48.0 -4.136986301369863, 73375200, 48.0 -4.1438356164383565, 73461600, 48.0 -4.1506849315068495, 73548000, 48.0 -4.157534246575342, 73634400, 48.0 -4.164383561643835, 73720800, 48.0 -4.171232876712328, 73807200, 48.0 -4.178082191780822, 73893600, 48.0 -4.184931506849315, 73980000, 48.0 -4.191780821917808, 74066400, 48.0 -4.198630136986301, 74152800, 48.0 -4.205479452054795, 74239200, 48.0 -4.212328767123288, 74325600, 48.0 -4.219178082191781, 74412000, 45.0 -4.226027397260274, 74493000, 45.0 -4.232876712328767, 74574000, 45.0 -4.239726027397261, 74655000, 45.0 -4.2465753424657535, 74736000, 45.0 -4.2534246575342465, 74817000, 45.0 -4.260273972602739, 74898000, 45.0 -4.267123287671233, 74979000, 45.0 -4.273972602739726, 75060000, 45.0 -4.280821917808219, 75141000, 45.0 -4.287671232876712, 75222000, 45.0 -4.294520547945205, 75303000, 45.0 -4.301369863013699, 75384000, 45.0 -4.308219178082192, 75465000, 45.0 -4.315068493150685, 75546000, 45.0 -4.321917808219178, 75627000, 45.0 -4.328767123287672, 75708000, 45.0 -4.335616438356165, 75789000, 45.0 -4.342465753424658, 75870000, 45.0 -4.3493150684931505, 75951000, 45.0 -4.3561643835616435, 76032000, 45.0 -4.363013698630137, 76113000, 45.0 -4.36986301369863, 76194000, 45.0 -4.376712328767123, 76275000, 45.0 -4.383561643835616, 76356000, 45.0 -4.390410958904109, 76437000, 45.0 -4.397260273972603, 76518000, 45.0 -4.404109589041096, 76599000, 45.0 -4.410958904109589, 76680000, 45.0 -4.417808219178082, 76761000, 45.0 -4.424657534246576, 76842000, 45.0 -4.431506849315069, 76923000, 45.0 -4.438356164383562, 77004000, 45.0 -4.445205479452055, 77085000, 45.0 -4.4520547945205475, 77166000, 45.0 -4.458904109589041, 77247000, 45.0 -4.465753424657534, 77328000, 42.0 -4.472602739726027, 77403600, 42.0 -4.47945205479452, 77479200, 42.0 -4.486301369863014, 77554800, 42.0 -4.493150684931507, 77630400, 42.0 -4.5, 77706000, 42.0 -4.506849315068493, 77781600, 42.0 -4.513698630136986, 77857200, 42.0 -4.52054794520548, 77932800, 42.0 -4.527397260273973, 78008400, 42.0 -4.534246575342466, 78084000, 42.0 -4.541095890410959, 78159600, 42.0 -4.5479452054794525, 78235200, 42.0 -4.554794520547945, 78310800, 42.0 -4.561643835616438, 78386400, 42.0 -4.568493150684931, 78462000, 42.0 -4.575342465753424, 78537600, 42.0 -4.582191780821918, 78613200, 42.0 -4.589041095890411, 78688800, 42.0 -4.595890410958904, 78764400, 42.0 -4.602739726027397, 78840000, 42.0 -4.609589041095891, 78915600, 42.0 -4.616438356164384, 78991200, 42.0 -4.623287671232877, 79066800, 42.0 -4.63013698630137, 79142400, 42.0 -4.636986301369863, 79218000, 42.0 -4.6438356164383565, 79293600, 42.0 -4.6506849315068495, 79369200, 42.0 -4.657534246575342, 79444800, 42.0 -4.664383561643835, 79520400, 42.0 -4.671232876712328, 79596000, 42.0 -4.678082191780822, 79671600, 42.0 -4.684931506849315, 79747200, 42.0 -4.691780821917808, 79822800, 42.0 -4.698630136986301, 79898400, 42.0 -4.705479452054795, 79974000, 42.0 -4.712328767123288, 80049600, 39.0 -4.719178082191781, 80119800, 39.0 -4.726027397260274, 80190000, 39.0 -4.732876712328767, 80260200, 39.0 -4.739726027397261, 80330400, 39.0 -4.7465753424657535, 80400600, 39.0 -4.7534246575342465, 80470800, 39.0 -4.760273972602739, 80541000, 39.0 -4.767123287671233, 80611200, 39.0 -4.773972602739726, 80681400, 39.0 -4.780821917808219, 80751600, 39.0 -4.787671232876712, 80821800, 39.0 -4.794520547945205, 80892000, 39.0 -4.801369863013699, 80962200, 39.0 -4.808219178082192, 81032400, 39.0 -4.815068493150685, 81102600, 39.0 -4.821917808219178, 81172800, 39.0 -4.828767123287672, 81243000, 39.0 -4.835616438356165, 81313200, 39.0 -4.842465753424658, 81383400, 39.0 -4.8493150684931505, 81453600, 39.0 -4.8561643835616435, 81523800, 39.0 -4.863013698630137, 81594000, 39.0 -4.86986301369863, 81664200, 39.0 -4.876712328767123, 81734400, 39.0 -4.883561643835616, 81804600, 39.0 -4.890410958904109, 81874800, 39.0 -4.897260273972603, 81945000, 39.0 -4.904109589041096, 82015200, 39.0 -4.910958904109589, 82085400, 39.0 -4.917808219178082, 82155600, 39.0 -4.924657534246576, 82225800, 39.0 -4.931506849315069, 82296000, 39.0 -4.938356164383562, 82366200, 39.0 -4.945205479452055, 82436400, 39.0 -4.9520547945205475, 82506600, 39.0 -4.958904109589041, 82576800, 36.0 -4.965753424657534, 82641600, 36.0 -4.972602739726027, 82706400, 36.0 -4.97945205479452, 82771200, 36.0 -4.986301369863014, 82836000, 36.0 -4.993150684931507, 82900800, 36.0 -5.0, 82965600, 36.0 -5.006849315068493, 83030400, 36.0 -5.013698630136986, 83095200, 36.0 -5.02054794520548, 83160000, 36.0 -5.027397260273973, 83224800, 36.0 -5.034246575342466, 83289600, 36.0 -5.041095890410959, 83354400, 36.0 -5.0479452054794525, 83419200, 36.0 -5.054794520547945, 83484000, 36.0 -5.061643835616438, 83548800, 36.0 -5.068493150684931, 83613600, 36.0 -5.075342465753424, 83678400, 36.0 -5.082191780821918, 83743200, 36.0 -5.089041095890411, 83808000, 36.0 -5.095890410958904, 83872800, 36.0 -5.102739726027397, 83937600, 36.0 -5.109589041095891, 84002400, 36.0 -5.116438356164384, 84067200, 36.0 -5.123287671232877, 84132000, 36.0 -5.13013698630137, 84196800, 36.0 -5.136986301369863, 84261600, 36.0 -5.1438356164383565, 84326400, 36.0 -5.1506849315068495, 84391200, 36.0 -5.157534246575342, 84456000, 36.0 -5.164383561643835, 84520800, 36.0 -5.171232876712328, 84585600, 36.0 -5.178082191780822, 84650400, 36.0 -5.184931506849315, 84715200, 36.0 -5.191780821917808, 84780000, 36.0 -5.198630136986301, 84844800, 36.0 -5.205479452054795, 84909600, 33.0 -5.212328767123288, 84969000, 33.0 -5.219178082191781, 85028400, 33.0 -5.226027397260274, 85087800, 33.0 -5.232876712328767, 85147200, 33.0 -5.239726027397261, 85206600, 33.0 -5.2465753424657535, 85266000, 33.0 -5.2534246575342465, 85325400, 33.0 -5.260273972602739, 85384800, 33.0 -5.267123287671233, 85444200, 33.0 -5.273972602739726, 85503600, 33.0 -5.280821917808219, 85563000, 33.0 -5.287671232876712, 85622400, 33.0 -5.294520547945205, 85681800, 33.0 -5.301369863013699, 85741200, 33.0 -5.308219178082192, 85800600, 33.0 -5.315068493150685, 85860000, 33.0 -5.321917808219178, 85919400, 33.0 -5.328767123287672, 85978800, 33.0 -5.335616438356165, 86038200, 33.0 -5.342465753424658, 86097600, 33.0 -5.3493150684931505, 86157000, 33.0 -5.3561643835616435, 86216400, 33.0 -5.363013698630137, 86275800, 33.0 -5.36986301369863, 86335200, 33.0 -5.376712328767123, 86394600, 33.0 -5.383561643835616, 86454000, 33.0 -5.390410958904109, 86513400, 33.0 -5.397260273972603, 86572800, 33.0 -5.404109589041096, 86632200, 33.0 -5.410958904109589, 86691600, 33.0 -5.417808219178082, 86751000, 33.0 -5.424657534246576, 86810400, 33.0 -5.431506849315069, 86869800, 33.0 -5.438356164383562, 86929200, 33.0 -5.445205479452055, 86988600, 33.0 -5.4520547945205475, 87048000, 30.0 -5.458904109589041, 87102000, 30.0 -5.465753424657534, 87156000, 30.0 -5.472602739726027, 87210000, 30.0 -5.47945205479452, 87264000, 30.0 -5.486301369863014, 87318000, 30.0 -5.493150684931507, 87372000, 30.0 -5.5, 87426000, 30.0 -5.506849315068493, 87480000, 30.0 -5.513698630136986, 87534000, 30.0 -5.52054794520548, 87588000, 30.0 -5.527397260273973, 87642000, 30.0 -5.534246575342466, 87696000, 30.0 -5.541095890410959, 87750000, 30.0 -5.5479452054794525, 87804000, 30.0 -5.554794520547945, 87858000, 30.0 -5.561643835616438, 87912000, 30.0 -5.568493150684931, 87966000, 30.0 -5.575342465753424, 88020000, 30.0 -5.582191780821918, 88074000, 30.0 -5.589041095890411, 88128000, 30.0 -5.595890410958904, 88182000, 30.0 -5.602739726027397, 88236000, 30.0 -5.609589041095891, 88290000, 30.0 -5.616438356164384, 88344000, 30.0 -5.623287671232877, 88398000, 30.0 -5.63013698630137, 88452000, 30.0 -5.636986301369863, 88506000, 30.0 -5.6438356164383565, 88560000, 30.0 -5.6506849315068495, 88614000, 30.0 -5.657534246575342, 88668000, 30.0 -5.664383561643835, 88722000, 30.0 -5.671232876712328, 88776000, 30.0 -5.678082191780822, 88830000, 30.0 -5.684931506849315, 88884000, 30.0 -5.691780821917808, 88938000, 30.0 -5.698630136986301, 88992000, 27.0 -5.705479452054795, 89040600, 27.0 -5.712328767123288, 89089200, 27.0 -5.719178082191781, 89137800, 27.0 -5.726027397260274, 89186400, 27.0 -5.732876712328767, 89235000, 27.0 -5.739726027397261, 89283600, 27.0 -5.7465753424657535, 89332200, 27.0 -5.7534246575342465, 89380800, 27.0 -5.760273972602739, 89429400, 27.0 -5.767123287671233, 89478000, 27.0 -5.773972602739726, 89526600, 27.0 -5.780821917808219, 89575200, 27.0 -5.787671232876712, 89623800, 27.0 -5.794520547945205, 89672400, 27.0 -5.801369863013699, 89721000, 27.0 -5.808219178082192, 89769600, 27.0 -5.815068493150685, 89818200, 27.0 -5.821917808219178, 89866800, 27.0 -5.828767123287672, 89915400, 27.0 -5.835616438356165, 89964000, 27.0 -5.842465753424658, 90012600, 27.0 -5.8493150684931505, 90061200, 27.0 -5.8561643835616435, 90109800, 27.0 -5.863013698630137, 90158400, 27.0 -5.86986301369863, 90207000, 27.0 -5.876712328767123, 90255600, 27.0 -5.883561643835616, 90304200, 27.0 -5.890410958904109, 90352800, 27.0 -5.897260273972603, 90401400, 27.0 -5.904109589041096, 90450000, 27.0 -5.910958904109589, 90498600, 27.0 -5.917808219178082, 90547200, 27.0 -5.924657534246576, 90595800, 27.0 -5.931506849315069, 90644400, 27.0 -5.938356164383562, 90693000, 27.0 -5.945205479452055, 90741600, 24.0 -5.9520547945205475, 90784800, 24.0 -5.958904109589041, 90828000, 24.0 -5.965753424657534, 90871200, 24.0 -5.972602739726027, 90914400, 24.0 -5.97945205479452, 90957600, 24.0 -5.986301369863014, 91000800, 24.0 -5.993150684931507, 91044000, 24.0 -6.0, 91087200, 24.0 -6.006849315068493, 91130400, 24.0 -6.013698630136986, 91173600, 24.0 -6.02054794520548, 91216800, 24.0 -6.027397260273973, 91260000, 24.0 -6.034246575342466, 91303200, 24.0 -6.041095890410959, 91346400, 24.0 -6.0479452054794525, 91389600, 24.0 -6.054794520547945, 91432800, 24.0 -6.061643835616438, 91476000, 24.0 -6.068493150684931, 91519200, 24.0 -6.075342465753424, 91562400, 24.0 -6.082191780821918, 91605600, 24.0 -6.089041095890411, 91648800, 24.0 -6.095890410958904, 91692000, 24.0 -6.102739726027397, 91735200, 24.0 -6.109589041095891, 91778400, 24.0 -6.116438356164384, 91821600, 24.0 -6.123287671232877, 91864800, 24.0 -6.13013698630137, 91908000, 24.0 -6.136986301369863, 91951200, 24.0 -6.1438356164383565, 91994400, 24.0 -6.1506849315068495, 92037600, 24.0 -6.157534246575342, 92080800, 24.0 -6.164383561643835, 92124000, 24.0 -6.171232876712328, 92167200, 24.0 -6.178082191780822, 92210400, 24.0 -6.184931506849315, 92253600, 24.0 -6.191780821917808, 92296800, 21.0 -6.198630136986301, 92334600, 21.0 -6.205479452054795, 92372400, 21.0 -6.212328767123288, 92410200, 21.0 -6.219178082191781, 92448000, 21.0 -6.226027397260274, 92485800, 21.0 -6.232876712328767, 92523600, 21.0 -6.239726027397261, 92561400, 21.0 -6.2465753424657535, 92599200, 21.0 -6.2534246575342465, 92637000, 21.0 -6.260273972602739, 92674800, 21.0 -6.267123287671233, 92712600, 21.0 -6.273972602739726, 92750400, 21.0 -6.280821917808219, 92788200, 21.0 -6.287671232876712, 92826000, 21.0 -6.294520547945205, 92863800, 21.0 -6.301369863013699, 92901600, 21.0 -6.308219178082192, 92939400, 21.0 -6.315068493150685, 92977200, 21.0 -6.321917808219178, 93015000, 21.0 -6.328767123287672, 93052800, 21.0 -6.335616438356165, 93090600, 21.0 -6.342465753424658, 93128400, 21.0 -6.3493150684931505, 93166200, 21.0 -6.3561643835616435, 93204000, 21.0 -6.363013698630137, 93241800, 21.0 -6.36986301369863, 93279600, 21.0 -6.376712328767123, 93317400, 21.0 -6.383561643835616, 93355200, 21.0 -6.390410958904109, 93393000, 21.0 -6.397260273972603, 93430800, 21.0 -6.404109589041096, 93468600, 21.0 -6.410958904109589, 93506400, 21.0 -6.417808219178082, 93544200, 21.0 -6.424657534246576, 93582000, 21.0 -6.431506849315069, 93619800, 21.0 -6.438356164383562, 93657600, 18.0 -6.445205479452055, 93690000, 18.0 -6.4520547945205475, 93722400, 18.0 -6.458904109589041, 93754800, 18.0 -6.465753424657534, 93787200, 18.0 -6.472602739726027, 93819600, 18.0 -6.47945205479452, 93852000, 18.0 -6.486301369863014, 93884400, 18.0 -6.493150684931507, 93916800, 18.0 -6.5, 93949200, 18.0 -6.506849315068493, 93981600, 18.0 -6.513698630136986, 94014000, 18.0 -6.52054794520548, 94046400, 18.0 -6.527397260273973, 94078800, 18.0 -6.534246575342466, 94111200, 18.0 -6.541095890410959, 94143600, 18.0 -6.5479452054794525, 94176000, 18.0 -6.554794520547945, 94208400, 18.0 -6.561643835616438, 94240800, 18.0 -6.568493150684931, 94273200, 18.0 -6.575342465753424, 94305600, 18.0 -6.582191780821918, 94338000, 18.0 -6.589041095890411, 94370400, 18.0 -6.595890410958904, 94402800, 18.0 -6.602739726027397, 94435200, 18.0 -6.609589041095891, 94467600, 18.0 -6.616438356164384, 94500000, 18.0 -6.623287671232877, 94532400, 18.0 -6.63013698630137, 94564800, 18.0 -6.636986301369863, 94597200, 18.0 -6.6438356164383565, 94629600, 18.0 -6.6506849315068495, 94662000, 18.0 -6.657534246575342, 94694400, 18.0 -6.664383561643835, 94726800, 18.0 -6.671232876712328, 94759200, 18.0 -6.678082191780822, 94791600, 18.0 -6.684931506849315, 94824000, 15.0 -6.691780821917808, 94851000, 15.0 -6.698630136986301, 94878000, 15.0 -6.705479452054795, 94905000, 15.0 -6.712328767123288, 94932000, 15.0 -6.719178082191781, 94959000, 15.0 -6.726027397260274, 94986000, 15.0 -6.732876712328767, 95013000, 15.0 -6.739726027397261, 95040000, 15.0 -6.7465753424657535, 95067000, 15.0 -6.7534246575342465, 95094000, 15.0 -6.760273972602739, 95121000, 15.0 -6.767123287671233, 95148000, 15.0 -6.773972602739726, 95175000, 15.0 -6.780821917808219, 95202000, 15.0 -6.787671232876712, 95229000, 15.0 -6.794520547945205, 95256000, 15.0 -6.801369863013699, 95283000, 15.0 -6.808219178082192, 95310000, 15.0 -6.815068493150685, 95337000, 15.0 -6.821917808219178, 95364000, 15.0 -6.828767123287672, 95391000, 15.0 -6.835616438356165, 95418000, 15.0 -6.842465753424658, 95445000, 15.0 -6.8493150684931505, 95472000, 15.0 -6.8561643835616435, 95499000, 15.0 -6.863013698630137, 95526000, 15.0 -6.86986301369863, 95553000, 15.0 -6.876712328767123, 95580000, 15.0 -6.883561643835616, 95607000, 15.0 -6.890410958904109, 95634000, 15.0 -6.897260273972603, 95661000, 15.0 -6.904109589041096, 95688000, 15.0 -6.910958904109589, 95715000, 15.0 -6.917808219178082, 95742000, 15.0 -6.924657534246576, 95769000, 15.0 -6.931506849315069, 95796000, 12.0 -6.938356164383562, 95817600, 12.0 -6.945205479452055, 95839200, 12.0 -6.9520547945205475, 95860800, 12.0 -6.958904109589041, 95882400, 12.0 -6.965753424657534, 95904000, 12.0 -6.972602739726027, 95925600, 12.0 -6.97945205479452, 95947200, 12.0 -6.986301369863014, 95968800, 12.0 -6.993150684931507, 95990400, 12.0 -7.0, 96012000, 12.0 -7.006849315068493, 96033600, 12.0 -7.013698630136986, 96055200, 12.0 -7.02054794520548, 96076800, 12.0 -7.027397260273973, 96098400, 12.0 -7.034246575342466, 96120000, 12.0 -7.041095890410959, 96141600, 12.0 -7.0479452054794525, 96163200, 12.0 -7.054794520547945, 96184800, 12.0 -7.061643835616438, 96206400, 12.0 -7.068493150684931, 96228000, 12.0 -7.075342465753424, 96249600, 12.0 -7.082191780821918, 96271200, 12.0 -7.089041095890411, 96292800, 12.0 -7.095890410958904, 96314400, 12.0 -7.102739726027397, 96336000, 12.0 -7.109589041095891, 96357600, 12.0 -7.116438356164384, 96379200, 12.0 -7.123287671232877, 96400800, 12.0 -7.13013698630137, 96422400, 12.0 -7.136986301369863, 96444000, 12.0 -7.1438356164383565, 96465600, 12.0 -7.1506849315068495, 96487200, 12.0 -7.157534246575342, 96508800, 12.0 -7.164383561643835, 96530400, 12.0 -7.171232876712328, 96552000, 12.0 -7.178082191780822, 96573600, 9.0 -7.184931506849315, 96589800, 9.0 -7.191780821917808, 96606000, 9.0 -7.198630136986301, 96622200, 9.0 -7.205479452054795, 96638400, 9.0 -7.212328767123288, 96654600, 9.0 -7.219178082191781, 96670800, 9.0 -7.226027397260274, 96687000, 9.0 -7.232876712328767, 96703200, 9.0 -7.239726027397261, 96719400, 9.0 -7.2465753424657535, 96735600, 9.0 -7.2534246575342465, 96751800, 9.0 -7.260273972602739, 96768000, 9.0 -7.267123287671233, 96784200, 9.0 -7.273972602739726, 96800400, 9.0 -7.280821917808219, 96816600, 9.0 -7.287671232876712, 96832800, 9.0 -7.294520547945205, 96849000, 9.0 -7.301369863013699, 96865200, 9.0 -7.308219178082192, 96881400, 9.0 -7.315068493150685, 96897600, 9.0 -7.321917808219178, 96913800, 9.0 -7.328767123287672, 96930000, 9.0 -7.335616438356165, 96946200, 9.0 -7.342465753424658, 96962400, 9.0 -7.3493150684931505, 96978600, 9.0 -7.3561643835616435, 96994800, 9.0 -7.363013698630137, 97011000, 9.0 -7.36986301369863, 97027200, 9.0 -7.376712328767123, 97043400, 9.0 -7.383561643835616, 97059600, 9.0 -7.390410958904109, 97075800, 9.0 -7.397260273972603, 97092000, 9.0 -7.404109589041096, 97108200, 9.0 -7.410958904109589, 97124400, 9.0 -7.417808219178082, 97140600, 9.0 -7.424657534246576, 97156800, 6.0 -7.431506849315069, 97167600, 6.0 -7.438356164383562, 97178400, 6.0 -7.445205479452055, 97189200, 6.0 -7.4520547945205475, 97200000, 6.0 -7.458904109589041, 97210800, 6.0 -7.465753424657534, 97221600, 6.0 -7.472602739726027, 97232400, 6.0 -7.47945205479452, 97243200, 6.0 -7.486301369863014, 97254000, 6.0 -7.493150684931507, 97264800, 6.0 -7.5, 97275600, 6.0 -7.506849315068493, 97286400, 6.0 -7.513698630136986, 97297200, 6.0 -7.52054794520548, 97308000, 6.0 -7.527397260273973, 97318800, 6.0 -7.534246575342466, 97329600, 6.0 -7.541095890410959, 97340400, 6.0 -7.5479452054794525, 97351200, 6.0 -7.554794520547945, 97362000, 6.0 -7.561643835616438, 97372800, 6.0 -7.568493150684931, 97383600, 6.0 -7.575342465753424, 97394400, 6.0 -7.582191780821918, 97405200, 6.0 -7.589041095890411, 97416000, 6.0 -7.595890410958904, 97426800, 6.0 -7.602739726027397, 97437600, 6.0 -7.609589041095891, 97448400, 6.0 -7.616438356164384, 97459200, 6.0 -7.623287671232877, 97470000, 6.0 -7.63013698630137, 97480800, 6.0 -7.636986301369863, 97491600, 6.0 -7.6438356164383565, 97502400, 6.0 -7.6506849315068495, 97513200, 6.0 -7.657534246575342, 97524000, 6.0 -7.664383561643835, 97534800, 6.0 -7.671232876712328, 97545600, 3.0 -7.678082191780822, 97551000, 3.0 -7.684931506849315, 97556400, 3.0 -7.691780821917808, 97561800, 3.0 -7.698630136986301, 97567200, 3.0 -7.705479452054795, 97572600, 3.0 -7.712328767123288, 97578000, 3.0 -7.719178082191781, 97583400, 3.0 -7.726027397260274, 97588800, 3.0 -7.732876712328767, 97594200, 3.0 -7.739726027397261, 97599600, 3.0 -7.7465753424657535, 97605000, 3.0 -7.7534246575342465, 97610400, 3.0 -7.760273972602739, 97615800, 3.0 -7.767123287671233, 97621200, 3.0 -7.773972602739726, 97626600, 3.0 -7.780821917808219, 97632000, 3.0 -7.787671232876712, 97637400, 3.0 -7.794520547945205, 97642800, 3.0 -7.801369863013699, 97648200, 3.0 -7.808219178082192, 97653600, 3.0 -7.815068493150685, 97659000, 3.0 -7.821917808219178, 97664400, 3.0 -7.828767123287672, 97669800, 3.0 -7.835616438356165, 97675200, 3.0 -7.842465753424658, 97680600, 3.0 -7.8493150684931505, 97686000, 3.0 -7.8561643835616435, 97691400, 3.0 -7.863013698630137, 97696800, 3.0 -7.86986301369863, 97702200, 3.0 -7.876712328767123, 97707600, 3.0 -7.883561643835616, 97713000, 3.0 -7.890410958904109, 97718400, 3.0 -7.897260273972603, 97723800, 3.0 -7.904109589041096, 97729200, 3.0 -7.910958904109589, 97734600, 3.0 -7.917808219178082, 97740000, 0.0 -7.924657534246576, 97740000, 0.0 -7.931506849315069, 97740000, 0.0 -7.938356164383562, 97740000, 0.0 -7.945205479452055, 97740000, 0.0 -7.9520547945205475, 97740000, 0.0 -7.958904109589041, 97740000, 0.0 -7.965753424657534, 97740000, 0.0 -7.972602739726027, 97740000, 0.0 -7.97945205479452, 97740000, 0.0 -7.986301369863014, 97740000, 0.0 -7.993150684931507, 97740000, 0.0 diff --git a/ergo-core/src/test/scala/org/ergoplatform/tools/emissionPlot.gnu b/ergo-core/src/test/scala/org/ergoplatform/tools/emissionPlot.gnu deleted file mode 100644 index f750368869..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/tools/emissionPlot.gnu +++ /dev/null @@ -1,20 +0,0 @@ -set print "-" - -set term png -#set terminal png enhanced size 1280, 1024 font ',20' -set terminal png enhanced font ',20' -set xlabel "Time (years)" font ",20" -set tics font ", 20" -set key font ",20" -set style line 1 lt 20 lw 4 linecolor 7 - -set output "EmissionCurve.png" -set ylabel "Coins total" font ",20" - -plot 'emission.csv' using 1:2 with lines ls 1 notitle - -set output "EmissionRate.png" - -set ylabel "Coins per block" font ",20" - -plot 'emission.csv' using 1:3 with lines ls 1 notitle diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala deleted file mode 100644 index 7ec6cd2466..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoPropertyTest.scala +++ /dev/null @@ -1,13 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.utils.generators.{ErgoGenerators, ValidBlocksGenerators} -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.testkit.utils.NoShrink - -trait ErgoPropertyTest extends AnyPropSpec - with ScalaCheckPropertyChecks - with ErgoTestHelpers - with ErgoGenerators - with NoShrink - with ValidBlocksGenerators diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala deleted file mode 100644 index 51d7e80597..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala +++ /dev/null @@ -1,112 +0,0 @@ -package org.ergoplatform.utils - -import akka.util.Timeout -import org.ergoplatform.mining.difficulty.DifficultyAdjustment -import org.ergoplatform.mining.emission.EmissionRules -import org.ergoplatform.mining.{AutolykosPowScheme, DefaultFakePowScheme} -import org.ergoplatform.modifiers.history.extension.ExtensionCandidate -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.sdk.wallet.secrets.ExtendedSecretKey -import org.ergoplatform.settings.Constants.HashLength -import org.ergoplatform.settings.Parameters.{MaxBlockCostIncrease, MinValuePerByteIncrease} -import org.ergoplatform.settings.ValidationRules._ -import org.ergoplatform.settings._ -import org.ergoplatform.wallet.interface4j.SecretString -import org.ergoplatform.wallet.interpreter.{ErgoInterpreter, ErgoProvingInterpreter} -import org.ergoplatform.wallet.mnemonic.Mnemonic -import org.ergoplatform.{DataInput, ErgoBox, ErgoTreePredef} -import scorex.core.app.Version -import scorex.core.network.PeerSpec -import scorex.crypto.authds.ADDigest -import scorex.crypto.hash.Digest32 -import scorex.util.ScorexLogging -import sigmastate.Values.ErgoTree -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.interpreter.{ContextExtension, ProverResult} - -import scala.concurrent.duration._ - -trait ErgoTestConstants extends ScorexLogging { - - implicit val votingSettings: VotingSettings = VotingSettings(1024, 32, 128, 32 * 1024, "01") - val validationSettings: ErgoValidationSettings = ErgoValidationSettings.initial - implicit val validationSettingsNoIl: ErgoValidationSettings = validationSettings - .updated(ErgoValidationSettingsUpdate(Seq(exIlUnableToValidate, exIlEncoding, exIlStructure, exEmpty), Seq())) - - val parameters: Parameters = LaunchParameters - - val extendedParameters: Parameters = { - // Randomness in tests is causing occasional cost overflow in the state context and insufficient box value - val extension = Map( - MaxBlockCostIncrease -> Math.ceil(parameters.parametersTable(MaxBlockCostIncrease) * 1.3).toInt, - MinValuePerByteIncrease -> (parameters.parametersTable(MinValuePerByteIncrease) - 30) - ) - Parameters(0, Parameters.DefaultParameters ++ extension, ErgoValidationSettingsUpdate.empty) - } - - val initSettings: ErgoSettings = ErgoSettings.read(Args(Some("src/test/resources/application.conf"), None)) - - implicit val settings: ErgoSettings = initSettings - - val nipopowAlgos = new NipopowAlgos(settings.chainSettings) - - val lightModeSettings: ErgoSettings = initSettings.copy( - nodeSettings = initSettings.nodeSettings.copy(stateType = StateType.Digest) - ) - - val emission: EmissionRules = settings.chainSettings.emissionRules - val coinsTotal: Long = emission.coinsTotal - val genesisStateDigest: ADDigest = settings.chainSettings.genesisStateDigest - val feeProp: ErgoTree = ErgoTreePredef.feeProposition(emission.settings.minerRewardDelay) - - val emptyProverResult: ProverResult = ProverResult(Array.emptyByteArray, ContextExtension.empty) - lazy val defaultSeed: Array[Byte] = Mnemonic.toSeed(settings.walletSettings.testMnemonic.fold[SecretString](SecretString.empty())(SecretString.create(_))) - val defaultRootSecret: ExtendedSecretKey = ExtendedSecretKey.deriveMasterKey(defaultSeed, usePre1627KeyDerivation = false) - val defaultChildSecrets: IndexedSeq[ExtendedSecretKey] = settings.walletSettings.testKeysQty - .toIndexedSeq - .flatMap(x => (0 until x).map(defaultRootSecret.child)) - val genesisBoxes: Seq[ErgoBox] = ErgoState.genesisBoxes(settings.chainSettings) - val genesisEmissionBox: ErgoBox = ErgoState.genesisBoxes(settings.chainSettings).head - val defaultProver: ErgoProvingInterpreter = ErgoProvingInterpreter( - defaultRootSecret +: defaultChildSecrets, parameters) - val defaultMinerSecret: DLogProverInput = defaultProver.hdKeys.head.privateInput - val defaultMinerSecretNumber: BigInt = defaultProver.hdKeys.head.privateInput.w - val defaultMinerPk: ProveDlog = defaultMinerSecret.publicImage - val defaultMinerPkPoint: EcPointType = defaultMinerPk.value - - val defaultTimestamp: Long = 1552217190000L - val defaultNBits: Long = settings.chainSettings.initialNBits - val defaultVotes: Array[Byte] = Array.fill(3)(0.toByte) - val defaultVersion: Byte = 0 - lazy val powScheme: AutolykosPowScheme = settings.chainSettings.powScheme.ensuring(_.isInstanceOf[DefaultFakePowScheme]) - val emptyVSUpdate = ErgoValidationSettingsUpdate.empty - val emptyStateContext: UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings, parameters) - .upcoming(defaultMinerPkPoint, defaultTimestamp, defaultNBits, defaultVotes, emptyVSUpdate, defaultVersion) - def stateContextWith(parameters: Parameters): UpcomingStateContext = ErgoStateContext.empty(genesisStateDigest, settings, parameters) - .upcoming(defaultMinerPkPoint, defaultTimestamp, defaultNBits, defaultVotes, emptyVSUpdate, defaultVersion) - val startHeight: Int = emptyStateContext.currentHeight - val startDigest: ADDigest = emptyStateContext.genesisStateDigest - - val EmptyStateRoot: ADDigest = ADDigest @@ Array.fill(HashLength + 1)(0.toByte) - val EmptyDigest32: Digest32 = Digest32 @@ Array.fill(HashLength)(0.toByte) - val defaultDifficultyControl = new DifficultyAdjustment(settings.chainSettings) - val defaultExtension: ExtensionCandidate = ExtensionCandidate(Seq(Array(0: Byte, 8: Byte) -> EmptyDigest32)) - val emptyExtension: ExtensionCandidate = ExtensionCandidate(Seq()) - val emptyDataInputs: IndexedSeq[DataInput] = IndexedSeq() - val emptyDataBoxes: IndexedSeq[ErgoBox] = IndexedSeq() - def emptyVerifier: ErgoInterpreter = ErgoInterpreter(emptyStateContext.currentParameters) - - val defaultTimeout: Timeout = Timeout(14.seconds) - val defaultAwaitDuration: FiniteDuration = defaultTimeout.duration + 1.second - - val defaultPeerSpec = PeerSpec( - settings.scorexSettings.network.agentName, - Version(settings.scorexSettings.network.appVersion), - settings.scorexSettings.network.nodeName, - None, - Seq.empty - ) - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala deleted file mode 100644 index bf9d61ac3e..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/ErgoTestHelpers.scala +++ /dev/null @@ -1,48 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.ErgoBoxCandidate -import org.ergoplatform.utils.generators.ValidBlocksGenerators -import org.scalatest.{EitherValues, OptionValues} -import scorex.core.network.peer.PeerInfo -import scorex.core.utils.ScorexEncoding -import scorex.util.ScorexLogging - -import java.net.InetSocketAddress -import java.util.concurrent.Executors -import scala.concurrent.{Await, ExecutionContext, Future} - -trait ErgoTestHelpers - extends ValidBlocksGenerators - with ScorexLogging - with ScorexEncoding - with OptionValues - with EitherValues { - - def await[A](f: Future[A]): A = Await.result[A](f, defaultAwaitDuration) - - def updateHeight(box: ErgoBoxCandidate, creationHeight: Int): ErgoBoxCandidate = - new ErgoBoxCandidate(box.value, box.ergoTree, creationHeight, box.additionalTokens, box.additionalRegisters) - - def changeValue(box: ErgoBoxCandidate, delta: Long): Option[ErgoBoxCandidate] = { - if (-delta >= box.value) { - None - } else { - Some(new ErgoBoxCandidate(Math.addExact(box.value, delta), box.ergoTree, box.creationHeight, - box.additionalTokens, box.additionalRegisters)) - } - } - - val inetAddr1 = new InetSocketAddress("92.92.92.92", 27017) - val inetAddr2 = new InetSocketAddress("93.93.93.93", 27017) - - val peers: Map[InetSocketAddress, PeerInfo] = Map( - inetAddr1 -> PeerInfo(defaultPeerSpec.copy(nodeName = "first"), System.currentTimeMillis()), - inetAddr2 -> PeerInfo(defaultPeerSpec.copy(nodeName = "second"), System.currentTimeMillis()) - ) -} - -object ErgoTestHelpers { - - implicit val defaultExecutionContext: ExecutionContext = - ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10)) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala deleted file mode 100644 index b38d920120..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala +++ /dev/null @@ -1,92 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.history.storage.modifierprocessors.{EmptyBlockSectionProcessor, FullBlockPruningProcessor, ToDownloadProcessor} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings._ -import org.scalacheck.Gen -import scorex.core.settings.ScorexSettings -import scorex.util.ModifierId -import scorex.util.encode.Base16 - -import scala.concurrent.duration._ - -trait HistoryTestHelpers extends ErgoPropertyTest { - - override lazy val smallInt: Gen[Int] = Gen.choose(0, BlocksInChain) - - val BlocksInChain = 10 - val BlocksToKeep: Int = BlocksInChain + 1 - - def ensureMinimalHeight(history: ErgoHistory, height: Int = BlocksInChain): ErgoHistory = { - val historyHeight = history.headersHeight - if (historyHeight < height) { - history match { - case _: EmptyBlockSectionProcessor => - val chain = genHeaderChain(height - historyHeight, history, diffBitsOpt = None, useRealTs = false) - if (history.isEmpty) applyHeaderChain(history, chain) else applyHeaderChain(history, chain.tail) - case _ => - ??? - } - } else { - history - } - } - - // todo looks like copy-paste from Stubs.generateHistory - def generateHistory(verifyTransactions: Boolean, - stateType: StateType, - PoPoWBootstrap: Boolean, - blocksToKeep: Int, - epochLength: Int = 100000000, - useLastEpochs: Int = 10, - initialDiffOpt: Option[BigInt] = None, - genesisIdOpt: Option[ModifierId] = None): ErgoHistory = { - - val txCostLimit = initSettings.nodeSettings.maxTransactionCost - val txSizeLimit = initSettings.nodeSettings.maxTransactionSize - val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(stateType, verifyTransactions, blocksToKeep, - UtxoSettings(false, 0, 2), NipopowSettings(false, 1), mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, - internalMinersCount = 1, internalMinerPollingInterval = 1.second, miningPubKeyHex = None, - offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, - rebroadcastCount = 200, 1000000, 100, adProofsSuffixLength = 112*1024, extraIndex = false -) - val scorexSettings: ScorexSettings = null - val walletSettings: WalletSettings = null - val chainSettings = initialDiffOpt match { - case Some(diff) => - val diffHex = Base16.encode(diff.toByteArray) - settings.chainSettings.copy(epochLength = epochLength, useLastEpochs = useLastEpochs, initialDifficultyHex = diffHex, genesisId = genesisIdOpt) - case _ => - settings.chainSettings.copy(epochLength = epochLength, useLastEpochs = useLastEpochs, genesisId = genesisIdOpt) - } - - val dir = createTempDir - val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, chainSettings, - nodeSettings, scorexSettings, walletSettings, settings.cacheSettings) - - ErgoHistory.readOrGenerate(fullHistorySettings)(null) - } - -} - -object HistoryTestHelpers { - - /** - * Use reflection to set `minimalFullBlockHeightVar` to 0 to change regular synchronization rule, that we - * first apply headers chain, and apply full blocks only after that - */ - def allowToApplyOldBlocks(history: ErgoHistory): Unit = { - import scala.reflect.runtime.{universe => ru} - val runtimeMirror = ru.runtimeMirror(getClass.getClassLoader) - val procInstance = runtimeMirror.reflect(history.asInstanceOf[ToDownloadProcessor]) - val ppM = ru.typeOf[ToDownloadProcessor].member(ru.TermName("pruningProcessor")).asMethod - val pp = procInstance.reflectMethod(ppM).apply().asInstanceOf[FullBlockPruningProcessor] - val f = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("minimalFullBlockHeightVar")).asTerm.accessed.asTerm - runtimeMirror.reflect(pp).reflectField(f).set(ErgoHistory.GenesisHeight) - val f2 = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("isHeadersChainSyncedVar")).asTerm.accessed.asTerm - runtimeMirror.reflect(pp).reflectField(f2).set(true) - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/MempoolTestHelpers.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/MempoolTestHelpers.scala deleted file mode 100644 index 2473790652..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/MempoolTestHelpers.scala +++ /dev/null @@ -1,39 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.ErgoBox.BoxId -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.{ErgoMemPoolReader, OrderedTxPool} -import scorex.util.ModifierId - -trait MempoolTestHelpers { - - // mempool reader stub specifically for this test only take is defined as only this method is used in rebroadcasting - class FakeMempool(txs: Seq[UnconfirmedTransaction]) extends ErgoMemPoolReader { - - override def modifierById(modifierId: ModifierId): Option[ErgoTransaction] = ??? - - override def getAll(ids: Seq[ModifierId]): Seq[UnconfirmedTransaction] = ??? - - override def size: Int = ??? - - override def weightedTransactionIds(limit: Int): Seq[OrderedTxPool.WeightedTxId] = ??? - - override def getAll: Seq[UnconfirmedTransaction] = ??? - - override def getAllPrioritized: Seq[UnconfirmedTransaction] = txs - - override def take(limit: Int): Iterable[UnconfirmedTransaction] = txs.take(limit) - - override def random(limit: Int): Iterable[UnconfirmedTransaction] = take(limit) - - override def spentInputs: Iterator[BoxId] = txs.map(_.transaction).flatMap(_.inputs).map(_.boxId).toIterator - - override def getRecommendedFee(expectedWaitTimeMinutes: Int, txSize: Int) : Long = 0 - - override def getExpectedWaitTime(txFee: Long, txSize: Int): Long = 0 - - } - -} - - diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala deleted file mode 100644 index 8df386a697..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala +++ /dev/null @@ -1,46 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.mining.DefaultFakePowScheme -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings.{ErgoSettings, NipopowSettings} - - -case class NodeViewTestConfig(stateType: StateType, - verifyTransactions: Boolean, - popowBootstrap: Boolean) { - - def toSettings: ErgoSettings = { - val defaultSettings = ErgoSettings.read() - defaultSettings.copy( - chainSettings = defaultSettings.chainSettings.copy( - powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n) - ), - nodeSettings = defaultSettings.nodeSettings.copy( - stateType = stateType, - verifyTransactions = verifyTransactions, - nipopowSettings = NipopowSettings(popowBootstrap, 1) - ) - ) - } - - override def toString: String = { - s"State: $stateType, Verify Transactions: $verifyTransactions, PoPoW Bootstrap: $popowBootstrap" - } -} - -object NodeViewTestConfig { - - def defaultConfig(config: ErgoSettings): ErgoSettings = config - - val allConfigs: List[NodeViewTestConfig] = List( - NodeViewTestConfig(StateType.Digest, verifyTransactions = true, popowBootstrap = true), - NodeViewTestConfig(StateType.Digest, verifyTransactions = false, popowBootstrap = true), - NodeViewTestConfig(StateType.Digest, verifyTransactions = false, popowBootstrap = false), - NodeViewTestConfig(StateType.Digest, verifyTransactions = true, popowBootstrap = false), - NodeViewTestConfig(StateType.Utxo, verifyTransactions = true, popowBootstrap = true), - NodeViewTestConfig(StateType.Utxo, verifyTransactions = true, popowBootstrap = false) - ) - - def verifyTxConfigs: List[NodeViewTestConfig] = NodeViewTestConfig.allConfigs.filter(_.verifyTransactions) - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestContext.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestContext.scala deleted file mode 100644 index 22aaef02c0..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestContext.scala +++ /dev/null @@ -1,12 +0,0 @@ -package org.ergoplatform.utils - -import akka.actor.{ActorRef, ActorSystem} -import akka.testkit.TestProbe -import org.ergoplatform.settings.ErgoSettings - -trait NodeViewTestContext { - def settings: ErgoSettings - def actorSystem: ActorSystem - def testProbe: TestProbe - def nodeViewHolderRef: ActorRef -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala deleted file mode 100644 index d78b852d81..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala +++ /dev/null @@ -1,157 +0,0 @@ -package org.ergoplatform.utils - -import akka.actor.ActorRef -import akka.pattern.ask -import akka.util.Timeout -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.{ErgoState, StateType, UtxoState} -import org.ergoplatform.settings.Algos -import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ -import scorex.core.validation.MalformedModifierError -import scorex.util.ModifierId - -import scala.concurrent.duration._ -import scala.reflect.ClassTag -import scala.util.{Failure, Success, Try} - -trait NodeViewBaseOps extends ErgoTestHelpers { - - type Ctx = NodeViewTestContext - type CurView = CurrentView[ErgoState[_]] - implicit private val timeout: Timeout = defaultTimeout - - def getCurrentView(implicit ctx: Ctx): CurView = { - val request = GetDataFromCurrentView[ErgoState[_], CurView](view => view) - await((nodeViewHolderRef ? request).mapTo[CurView]) - } - - def getHistory(implicit ctx: Ctx): ErgoHistory = getCurrentView.history - - def getCurrentState(implicit ctx: Ctx): ErgoState[_] = getCurrentView.state - - def verifyTransactions(implicit ctx: Ctx): Boolean = ctx.settings.nodeSettings.verifyTransactions - - def stateType(implicit ctx: Ctx): StateType = ctx.settings.nodeSettings.stateType - - def applyHeader(header: Header)(implicit ctx: Ctx): Try[Unit] = { - subscribeModificationOutcome() - nodeViewHolderRef ! LocallyGeneratedModifier(header) - expectModificationOutcome(header) - } - - def applyBlock(fullBlock: ErgoFullBlock, excludeExt: Boolean = false)(implicit ctx: Ctx): Try[Unit] = { - subscribeModificationOutcome() - nodeViewHolderRef ! LocallyGeneratedModifier(fullBlock.header) - expectModificationOutcome(fullBlock.header).flatMap(_ => applyPayload(fullBlock, excludeExt)) - } - - def applyPayload(fullBlock: ErgoFullBlock, excludeExt: Boolean = false)(implicit ctx: Ctx): Try[Unit] = { - subscribeModificationOutcome() - val sections = if (verifyTransactions && excludeExt) { - fullBlock.blockSections.filterNot(_.modifierTypeId == Extension.modifierTypeId) - } else if (verifyTransactions) { - fullBlock.blockSections - } else { - Seq.empty - } - sections.foldLeft(Success(()): Try[Unit]) { (lastResult, section) => - lastResult.flatMap { _ => - nodeViewHolderRef ! LocallyGeneratedModifier(section) - section match { - case Extension(_, Seq(), _) => Success(()) // doesn't send back any outcome - case _ => expectModificationOutcome(section) // normal flow - } - } - } - } - - def subscribeModificationOutcome()(implicit ctx: Ctx): Unit = { - subscribeEvents(classOf[SyntacticallySuccessfulModifier]) - subscribeEvents(classOf[SyntacticallyFailedModification]) - } - - def expectModificationOutcome(section: BlockSection)(implicit ctx: Ctx): Try[Unit] = { - expectMsgType[ModificationOutcome] match { - case SyntacticallySuccessfulModifier(_, modId) if modId == section.id => - Success(()) - case outcome => - val msg = section match { - case header: Header => s"Error applying header ${header.id}: $outcome" - case other => s"Error applying section $other: $outcome" - } - val e = new MalformedModifierError(msg, section.id, section.modifierTypeId) - log.error(msg, e) - Failure(e) - } - } - - /** Creates next block in chain from transactions, works only for UTXO configurations - */ - def makeNextBlock(utxoState: UtxoState, - txs: Seq[ErgoTransaction]) - (implicit ctx: Ctx): ErgoFullBlock = { - val time = System.currentTimeMillis() - val parent = getHistory.bestFullBlockOpt - validFullBlock(parent, utxoState, txs, Some(time)) - } - - @inline private def nodeViewHolderRef(implicit ctx: Ctx): ActorRef = ctx.nodeViewHolderRef - - @inline def send(msg: Any)(implicit ctx: Ctx): Unit = ctx.testProbe.send(nodeViewHolderRef, msg) - - @inline def ctxTimeout(implicit ctx: Ctx): FiniteDuration = ctx.testProbe.remainingOrDefault - - @inline def expectMsg[T](obj: T)(implicit ctx: Ctx): T = ctx.testProbe.expectMsg(obj) - - @inline def expectMsgType[T](implicit ctx: Ctx, t: ClassTag[T]): T = ctx.testProbe.expectMsgType - - @inline def expectNoMsg()(implicit ctx: Ctx): Unit = ctx.testProbe.expectNoMessage(ctxTimeout) - - @inline def ignoreMsg(f: PartialFunction[Any, Boolean])(implicit ctx: Ctx): Unit = ctx.testProbe.ignoreMsg(f) - - @inline def ignoreNoMsg()(implicit ctx: Ctx): Unit = ctx.testProbe.ignoreNoMsg() - - @inline def subscribeEvents(eventType: Class[_])(implicit ctx: Ctx): Boolean = { - ctx.actorSystem.eventStream.subscribe(ctx.testProbe.ref, eventType) - } - - @inline def unsubscribeEvents(eventType: Class[_])(implicit ctx: Ctx): Boolean = { - ctx.actorSystem.eventStream.unsubscribe(ctx.testProbe.ref, eventType) - } -} - -trait NodeViewTestOps extends NodeViewBaseOps { - - def getBestHeaderOpt(implicit ctx: Ctx): Option[Header] = getHistory.bestHeaderOpt - - def getPoolSize(implicit ctx: Ctx): Int = getCurrentView.pool.size - - def getRootHash(implicit ctx: Ctx): String = Algos.encode(getCurrentState.rootDigest) - - def getBestFullBlockOpt(implicit ctx: Ctx): Option[ErgoFullBlock] = getHistory.bestFullBlockOpt - - def getBestFullBlockEncodedId(implicit ctx: Ctx): Option[String] = getBestFullBlockOpt.map(_.header.encodedId) - - def getBestHeaderEncodedId(implicit ctx: Ctx): Option[String] = getBestHeaderOpt.map(_.encodedId) - - - def getHistoryHeight(implicit ctx: Ctx): Int = getHistory.headersHeight - - def getHeightOf(id: scorex.util.ModifierId)(implicit ctx: Ctx): Option[Int] = getHistory.heightOf(id) - - def getLastHeadersLength(count: Int)(implicit ctx: Ctx): Int = getHistory.lastHeaders(count).size - - def getModifierById(id: ModifierId)(implicit ctx: Ctx): Option[BlockSection] = getHistory.modifierById(id) - - def getGenesisStateDigest(implicit ctx: Ctx): Array[Byte] = - ctx.settings.chainSettings.genesisStateDigest - -} - -object NodeViewTestOps extends NodeViewTestOps diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/RandomLike.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/RandomLike.scala deleted file mode 100644 index fe4dfe6821..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/RandomLike.scala +++ /dev/null @@ -1,18 +0,0 @@ -package org.ergoplatform.utils - -import scala.util.Random - -trait RandomLike { - def nextInt(i: Int): Int - def nextBoolean(): Boolean - def nextLong(): Long - def nextDouble(): Double -} - -class RandomWrapper(seed: Option[Int] = None) extends RandomLike { - private[this] val rnd = seed.fold(new Random)(s => new Random(s)) - override def nextInt(i: Int): Int = rnd.nextInt(i) - override def nextBoolean(): Boolean = rnd.nextBoolean() - override def nextLong(): Long = rnd.nextLong() - override def nextDouble(): Double = rnd.nextDouble() -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/Stubs.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/Stubs.scala deleted file mode 100644 index b68886a573..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/Stubs.scala +++ /dev/null @@ -1,405 +0,0 @@ -package org.ergoplatform.utils - -import akka.actor.{Actor, ActorRef, ActorSystem, Props} -import akka.pattern.StatusReply -import org.bouncycastle.util.BigIntegers -import org.ergoplatform.P2PKAddress -import org.ergoplatform.mining.CandidateGenerator.Candidate -import org.ergoplatform.mining.{AutolykosSolution, CandidateGenerator, ErgoMiner, WorkMessage} -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction -import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.mempool.ErgoMemPool.{ProcessingOutcome, SortingOption} -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.nodeView.state.{DigestState, ErgoStateContext, StateType} -import org.ergoplatform.nodeView.wallet.ErgoWalletActor._ -import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult -import org.ergoplatform.nodeView.wallet._ -import org.ergoplatform.nodeView.wallet.persistence.WalletDigest -import org.ergoplatform.nodeView.wallet.scanning.Scan -import org.ergoplatform.sanity.ErgoSanity.HT -import org.ergoplatform.sdk.wallet.secrets.{DerivationPath, ExtendedSecretKey} -import org.ergoplatform.settings.Constants.HashLength -import org.ergoplatform.settings._ -import org.ergoplatform.utils.generators.{ChainGenerator, ErgoGenerators, ErgoTransactionGenerators} -import org.ergoplatform.wallet.Constants.{PaymentsScanId, ScanId} -import org.ergoplatform.wallet.boxes.{ChainStatus, TrackedBox} -import org.ergoplatform.wallet.interface4j.SecretString -import org.ergoplatform.wallet.interpreter.ErgoProvingInterpreter -import org.ergoplatform.wallet.mnemonic.Mnemonic -import org.ergoplatform.wallet.utils.TestFileUtils -import org.scalacheck.Gen -import scorex.core.app.Version -import scorex.core.network.NetworkController.ReceivableMessages.GetConnectedPeers -import scorex.core.network.peer.PeerManager.ReceivableMessages.{GetAllPeers, GetBlacklistedPeers} -import scorex.core.network.{Handshake, PeerSpec} -import scorex.core.settings.ScorexSettings -import scorex.crypto.authds.ADDigest -import scorex.crypto.hash.Digest32 -import scorex.db.ByteArrayWrapper -import scorex.util.Random -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} - -import scala.collection.mutable -import scala.concurrent.duration._ -import scala.util.{Failure, Success, Try} - -trait Stubs extends ErgoGenerators with ErgoTestHelpers with ChainGenerator with TestFileUtils { - - implicit val system: ActorSystem - - val chain: Seq[ErgoFullBlock] = genChain(6) - - val history: HT = applyChain(generateHistory(), chain) - - val digestState: DigestState = { - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, settings)).map { wus => - DigestState.create(Some(wus.version), Some(wus.rootDigest), createTempDir, settings) - } - }.sample.value - - val utxoSettings: ErgoSettings = settings.copy(nodeSettings = settings.nodeSettings.copy(stateType = StateType.Utxo)) - - val utxoState: WrappedUtxoState = - boxesHolderGen.map(WrappedUtxoState(_, createTempDir, None, parameters, utxoSettings)).sample.value - - lazy val wallet = new WalletStub - - val txs: Seq[ErgoTransaction] = validTransactionsFromBoxHolder(boxesHolderGen.sample.get)._1 - val memPool: ErgoMemPool = ErgoMemPool.empty(settings).put(txs.map(tx => UnconfirmedTransaction(tx, None))) - - val digestReaders = Readers(history, digestState, memPool, wallet) - - val utxoReaders = Readers(history, utxoState, memPool, wallet) - - val protocolVersion = Version("1.1.1") - - val peerSpec: PeerSpec = defaultPeerSpec.copy(protocolVersion = protocolVersion) - - val connectedPeers: Seq[Handshake] = Seq( - Handshake(peerSpec.copy(nodeName = "first"), System.currentTimeMillis() - 100), - Handshake(peerSpec.copy(nodeName = "second"), System.currentTimeMillis() + 100) - ) - - val blacklistedPeers: Seq[String] = Seq("4.4.4.4:1111", "8.8.8.8:2222") - - val pk: ProveDlog = DLogProverInput(BigIntegers.fromUnsignedByteArray(Random.randomBytes(32))).publicImage - val externalWorkMessage = WorkMessage(Array.fill(32)(2: Byte), BigInt(9999), None, pk, None) - - class PeersManagerStub extends Actor { - def receive: Receive = { - case GetAllPeers => sender() ! peers - case GetBlacklistedPeers => sender() ! blacklistedPeers - } - } - - object PeersManagerStub { - def props(): Props = Props(new PeersManagerStub) - } - - class MinerStub extends Actor { - def receive: Receive = { - case CandidateGenerator.GenerateCandidate(_, reply) => - if (reply) { - val candidate = Candidate(null, externalWorkMessage, Seq.empty) // API does not use CandidateBlock - sender() ! StatusReply.success(candidate) - } - case _: AutolykosSolution => sender() ! StatusReply.success(()) - case ErgoMiner.ReadMinerPk => sender() ! StatusReply.success(pk) - } - } - - object MinerStub { - def props(): Props = Props(new MinerStub) - } - - class NodeViewStub extends Actor { - def receive: Receive = { - case LocallyGeneratedTransaction(utx) => - sender() ! new ProcessingOutcome.Accepted(utx, System.currentTimeMillis()) - case _ => - } - } - - class FailingNodeViewStub extends Actor { - def receive: Receive = { - case LocallyGeneratedTransaction(_) => - sender() ! new ProcessingOutcome.Invalidated(new Error("Transaction invalid"), System.currentTimeMillis()) - case _ => - } - } - - object NodeViewStub { - def props(): Props = Props(new NodeViewStub) - def failingProps(): Props = Props(new FailingNodeViewStub) - } - - class NetworkControllerStub extends Actor { - def receive: Receive = { - case GetConnectedPeers => sender() ! connectedPeers - case _ => - } - } - - object NetworkControllerStub { - def props(): Props = Props(new NetworkControllerStub) - } - - class PeerManagerStub extends Actor { - def receive: Receive = { - case _ => - } - } - - object PeerManagerStub { - def props(): Props = Props(new PeerManagerStub) - } - - class WalletActorStub extends Actor { - - import WalletActorStub._ - - private val prover: ErgoProvingInterpreter = defaultProver - private val trackedAddresses: Seq[P2PKAddress] = prover.hdPubKeys.map(epk => P2PKAddress(epk.key)) - - private val apps = mutable.Map[ScanId, Scan]() - - private val ergoWalletService = new ErgoWalletServiceImpl(settings) - - def receive: Receive = { - - case _: InitWallet => sender() ! Success(SecretString.create(WalletActorStub.mnemonic)) - - case _: RestoreWallet => sender() ! Success(()) - - case _: UnlockWallet => sender() ! Success(()) - - case LockWallet => () - - case RescanWallet(_) => sender ! Success(()) - - case GetWalletStatus => sender() ! WalletStatus(true, true, None, ErgoHistory.GenesisHeight, error = None) - - case _: CheckSeed => sender() ! true - - case GetWalletBoxes(unspentOnly, _) => - val boxes = if (unspentOnly) { - Seq(walletBox10_10, walletBox20_30) - } else { - Seq(walletBox10_10, walletBox20_30, walletBoxSpent21_31) - } - sender() ! boxes.sortBy(_.trackedBox.inclusionHeightOpt) - - case GetScanTransactions(scanId, includeUnconfirmed) => - if (includeUnconfirmed) { - sender() ! ScanRelatedTxsResponse(walletTxsForScan(scanId, includeUnconfirmed = true)) - } else { - sender() ! ScanRelatedTxsResponse(walletTxsForScan(scanId)) - } - - case GetTransactions => - sender() ! walletTxs - - case DeriveKey(_) => sender() ! Success(WalletActorStub.address) - - case DeriveNextKey => sender() ! - DeriveNextKeyResult(Success((WalletActorStub.path, WalletActorStub.address, WalletActorStub.secretKey))) - - case ReadPublicKeys(from, until) => - sender() ! trackedAddresses.slice(from, until) - - case ReadBalances(chainStatus) => - sender() ! WalletDigest(0, WalletActorStub.balance(chainStatus), mutable.WrappedArray.empty) - - case AddScan(req) => - val scanId = ScanId @@ (apps.lastOption.map(_._1).getOrElse(100: Short) + 1).toShort - val app = req.toScan(scanId) - apps += scanId -> app.get - sender() ! AddScanResponse(app) - - case RemoveScan(scanId) => - val res: Try[Unit] = if(apps.exists(_._1 == scanId)) { - apps.remove(scanId) - Success(()) - } else { - Failure(new Exception("")) - } - sender() ! RemoveScanResponse(res) - - case GetScanUnspentBoxes(_, considerUnconfirmed, minHeight, maxHeight) => - val unfiltered = if(considerUnconfirmed) { - Seq(walletBoxN_N) - } else { - Seq(walletBox10_10, walletBox20_30, walletBoxSpent21_31) - } - val res = unfiltered.filter { box => - box.trackedBox.inclusionHeightOpt.getOrElse(0) >= minHeight && - (maxHeight == -1 || box.trackedBox.inclusionHeightOpt.getOrElse(Int.MaxValue) <= maxHeight) - } - sender() ! res - - case GetScanSpentBoxes(_) => - sender() ! Seq(walletBox10_10, walletBox20_30, walletBoxSpent21_31) - - case StopTracking(_, _) => - sender() ! StopTrackingResponse(Success(())) - - case ReadScans => - sender() ! ReadScansResponse(apps.values.toSeq) - - case GenerateTransaction(_, _, _, _) => - val input = ErgoTransactionGenerators.inputGen.sample.value - val tx = ErgoTransaction(IndexedSeq(input), IndexedSeq(ergoBoxCandidateGen.sample.value)) - sender() ! Success(tx) - - case SignTransaction(tx, secrets, hints, boxesToSpendOpt, dataBoxesOpt) => - val sc = ErgoStateContext.empty(settings, parameters) - sender() ! ergoWalletService.signTransaction(Some(prover), tx, secrets, hints, boxesToSpendOpt, dataBoxesOpt, parameters, sc) { boxId => - utxoState.versionedBoxHolder.get(ByteArrayWrapper(boxId)) - } - } - } - - object WalletActorStub { - val mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon" - val path = DerivationPath(List(0, 1, 2), publicBranch = false) - val secretKey = ExtendedSecretKey.deriveMasterKey(Mnemonic.toSeed(SecretString.create(mnemonic)), usePre1627KeyDerivation = false).derive(path) - val address = P2PKAddress(proveDlogGen.sample.get) - - val walletBoxN_N: WalletBox = WalletBox( - TrackedBox( - creationTxId = modifierIdGen.sample.get, - creationOutIndex = 0, - inclusionHeightOpt = None, - spendingTxIdOpt = Some(modifierIdGen.sample.get), - spendingHeightOpt = None, - box = ergoBoxGen.sample.get, - scans = Set(PaymentsScanId) - ), - confirmationsNumOpt = None - ) - - val walletBox10_10: WalletBox = WalletBox( - TrackedBox( - creationTxId = modifierIdGen.sample.get, - creationOutIndex = 0, - inclusionHeightOpt = Some(10), - spendingTxIdOpt = Some(modifierIdGen.sample.get), - spendingHeightOpt = None, - box = ergoBoxGen.sample.get, - scans = Set(PaymentsScanId) - ), - confirmationsNumOpt = Some(10) - ) - val walletBox20_30: WalletBox = walletBox10_10.copy( - confirmationsNumOpt = Some(20), - trackedBox = walletBox10_10.trackedBox.copy(inclusionHeightOpt = Some(30)) - ) - val walletBoxSpent21_31: WalletBox = walletBox10_10.copy( - confirmationsNumOpt = Some(21), - trackedBox = walletBox10_10.trackedBox.copy( - inclusionHeightOpt = Some(31), - spendingHeightOpt = Some(32), - spendingTxIdOpt = Some(modifierIdGen.sample.get) - ) - ) - val walletTxs: Seq[AugWalletTransaction] = - Gen.listOf(augWalletTransactionGen).sample.get - - def walletTxsForScan(scanId: ScanId, includeUnconfirmed: Boolean = false): Seq[AugWalletTransaction] = - Gen.listOf(augWalletTransactionForScanGen(scanId, includeUnconfirmed)).sample.get - - def props(): Props = Props(new WalletActorStub) - - def balance(chainStatus: ChainStatus): Long = if (chainStatus.onChain) confirmedBalance else unconfirmedBalance - - def confirmedBalance: Long = 1L - - def unconfirmedBalance: Long = 2L - } - - class WalletStub extends ErgoWalletReader { - val walletActor: ActorRef = system.actorOf(WalletActorStub.props()) - } - - - class DigestReadersStub extends Actor { - def receive: PartialFunction[Any, Unit] = { - case GetReaders => sender() ! digestReaders - case GetDataFromHistory(f) => sender() ! f(history) - } - } - - object DigestReadersStub { - def props(): Props = Props(new DigestReadersStub) - } - - class UtxoReadersStub extends Actor { - def receive: PartialFunction[Any, Unit] = { - case GetReaders => sender() ! utxoReaders - case GetDataFromHistory(f) => sender() ! f(history) - } - } - - object UtxoReadersStub { - def props(): Props = Props(new UtxoReadersStub) - } - - - lazy val digestReadersRef: ActorRef = system.actorOf(DigestReadersStub.props()) - lazy val utxoReadersRef: ActorRef = system.actorOf(UtxoReadersStub.props()) - - lazy val minerRef: ActorRef = system.actorOf(MinerStub.props()) - lazy val peerManagerRef: ActorRef = system.actorOf(PeerManagerStub.props()) - lazy val pmRef: ActorRef = system.actorOf(PeersManagerStub.props()) - lazy val nodeViewRef: ActorRef = system.actorOf(NodeViewStub.props()) - lazy val networkControllerRef: ActorRef = system.actorOf(NetworkControllerStub.props()) - - def generateHistory(verifyTransactions: Boolean = true, - stateType: StateType = StateType.Digest, - poPoWBootstrap: Boolean = false, - blocksToKeep: Int = 100, - epochLength: Int = 100000000, - useLastEpochs: Int = 10): ErgoHistory = { - - val txCostLimit = initSettings.nodeSettings.maxTransactionCost - val txSizeLimit = initSettings.nodeSettings.maxTransactionSize - val nodeSettings: NodeConfigurationSettings = NodeConfigurationSettings(stateType, verifyTransactions, blocksToKeep, - UtxoSettings(false, 0, 2), NipopowSettings(poPoWBootstrap, 1), mining = false, txCostLimit, txSizeLimit, useExternalMiner = false, - internalMinersCount = 1, internalMinerPollingInterval = 1.second,miningPubKeyHex = None, - offlineGeneration = false, 200, 5.minutes, 100000, 1.minute, mempoolSorting = SortingOption.FeePerByte, - rebroadcastCount = 200, 1000000, 100, adProofsSuffixLength = 112*1024, extraIndex = false -) - val scorexSettings: ScorexSettings = null - val walletSettings: WalletSettings = null - val chainSettings = settings.chainSettings.copy(epochLength = epochLength, useLastEpochs = useLastEpochs) - - val dir = createTempDir - val fullHistorySettings: ErgoSettings = ErgoSettings(dir.getAbsolutePath, NetworkType.TestNet, chainSettings, - nodeSettings, scorexSettings, walletSettings, settings.cacheSettings) - - ErgoHistory.readOrGenerate(fullHistorySettings)(null) - } - - def syntacticallyValidModifier(history: HT): Header = { - val bestTimestamp = history.bestHeaderOpt.map(_.timestamp + 1).getOrElse(System.currentTimeMillis()) - - powScheme.prove( - history.bestHeaderOpt, - Header.InitialVersion, - settings.chainSettings.initialNBits, - ADDigest @@ Array.fill(HashLength + 1)(0.toByte), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Math.max(System.currentTimeMillis(), bestTimestamp), - Digest32 @@ Array.fill(HashLength)(0.toByte), - Array.fill(3)(0: Byte), - defaultMinerSecretNumber - ).value - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/TestCase.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/TestCase.scala deleted file mode 100644 index 50d000026d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/TestCase.scala +++ /dev/null @@ -1,9 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.settings.Parameters -import org.ergoplatform.utils.fixtures.NodeViewFixture - -case class TestCase(name: String)(test: NodeViewFixture => Unit) { - def run(parameters: Parameters, c: NodeViewTestConfig): Unit = - new NodeViewFixture(c.toSettings, parameters).apply(test) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala deleted file mode 100644 index 42407311f2..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala +++ /dev/null @@ -1,142 +0,0 @@ -package org.ergoplatform.utils - -import org.ergoplatform.ErgoBox.TokenId -import org.ergoplatform._ -import org.ergoplatform.mining.CandidateGenerator -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.{ErgoState, UtxoState} -import org.ergoplatform.nodeView.wallet.ErgoWallet -import org.ergoplatform.nodeView.wallet.IdUtils._ -import org.ergoplatform.nodeView.wallet.persistence.WalletDigest -import org.ergoplatform.sdk.wallet.TokensMap -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.fixtures.WalletFixture -import scorex.crypto.authds.ADKey -import scorex.crypto.hash.Blake2b256 -import scorex.util.ModifierId -import sigma.Colls -import sigmastate.Values.ErgoTree -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.interpreter.ProverResult -import sigma.Extensions._ - -trait WalletTestOps extends NodeViewBaseOps { - - def newAssetIdStub: TokenId = Blake2b256.hash("new_asset").toTokenId - - def withFixture[T](test: WalletFixture => T): T = - new WalletFixture(settings, parameters, getCurrentView(_).vault).apply(test) - - def wallet(implicit w: WalletFixture): ErgoWallet = w.wallet - - def getPublicKeys(implicit w: WalletFixture): Seq[P2PKAddress] = - await(w.wallet.publicKeys(0, Int.MaxValue)) - - def getConfirmedBalances(implicit w: WalletFixture): WalletDigest = - await(w.wallet.confirmedBalances) - - def getBalancesWithUnconfirmed(implicit w: WalletFixture): WalletDigest = - await(w.wallet.balancesWithUnconfirmed) - - def offchainScanTime(tx: ErgoTransaction): Long = tx.outputs.size * 100 + 300 - - def balanceAmount(boxes: Seq[ErgoBox]): Long = boxes.map(_.value).sum - - def boxesAvailable(block: ErgoFullBlock, pk: ProveDlog): Seq[ErgoBox] = - block.transactions.flatMap(boxesAvailable(_, pk)) - - def boxesAvailable(tx: ErgoTransaction, pk: ProveDlog): Seq[ErgoBox] = - tx.outputs.filter(_.propositionBytes.containsSlice(org.ergoplatform.mining.groupElemToBytes(pk.value))) - - def assetAmount(boxes: Seq[ErgoBoxCandidate]): Seq[(ModifierId, Long)] = - assetsByTokenId(boxes).map { case (tokenId, sum) => (tokenId.toModifierId, sum) }.toArray[(ModifierId, Long)] - - def toAssetMap(assetSeq: Seq[(TokenId, Long)]): TokensMap = - assetSeq.map { case (tokenId, sum) => (tokenId.toModifierId, sum) }.toMap - - def assetsByTokenId(boxes: Seq[ErgoBoxCandidate]): Map[TokenId, Long] = { - boxes - .flatMap(_.additionalTokens.toArray) - .foldLeft(Map.empty[EncodedTokenId, Long]) { case (acc, (id, amt)) => - acc.updated(encodedTokenId(id), acc.getOrElse(encodedTokenId(id), 0L) + amt) - } - .map(x => decodedTokenId(x._1) -> x._2) - } - - def getUtxoState(implicit ctx: Ctx): UtxoState = getCurrentState.asInstanceOf[UtxoState] - - def getHeightOf(state: ErgoState[_])(implicit ctx: Ctx): Option[Int] = - getHistory.heightOf(scorex.core.versionToId(state.version)) - - def makeGenesisBlock(script: ProveDlog, assets: Seq[(TokenId, Long)] = Seq.empty) - (implicit ctx: Ctx): ErgoFullBlock = { - makeNextBlock(getUtxoState, Seq(makeGenesisTx(script, assets))) - } - - def makeGenesisTxWithAsset(publicKey: ProveDlog, issueAsset: Boolean): ErgoTransaction = { - val inputs = IndexedSeq(new Input(genesisEmissionBox.id, emptyProverResult)) - val assets: Seq[(TokenId, Long)] = if (issueAsset) { - Seq(inputs.head.boxId.toTokenId -> 1L) - } else { - Seq.empty - } - - CandidateGenerator.collectRewards(Some(genesisEmissionBox), - ErgoHistory.EmptyHistoryHeight, - Seq.empty, - publicKey, - emptyStateContext, - Colls.fromArray(assets.toArray)).head - } - - def makeGenesisTx(publicKey: ProveDlog, assetsIn: Seq[(TokenId, Long)] = Seq.empty): ErgoTransaction = { - val inputs = IndexedSeq(new Input(genesisEmissionBox.id, emptyProverResult)) - val assets: Seq[(TokenId, Long)] = replaceNewAssetStub(assetsIn, inputs) - CandidateGenerator.collectRewards(Some(genesisEmissionBox), - ErgoHistory.EmptyHistoryHeight, - Seq.empty, - publicKey, - emptyStateContext, - Colls.fromArray(assets.toArray)).head - } - - def makeSpendingTx(boxesToSpend: Seq[ErgoBox], - addressToReturn: ErgoAddress, - balanceToReturn: Long = 0, - assets: Seq[(TokenId, Long)] = Seq.empty): ErgoTransaction = { - makeTx(boxesToSpend, emptyProverResult, balanceToReturn, addressToReturn.script, assets) - } - - def makeTx(boxesToSpend: Seq[ErgoBox], - proofToSpend: ProverResult, - balanceToReturn: Long, - scriptToReturn: ErgoTree, - assets: Seq[(TokenId, Long)] = Seq.empty): ErgoTransaction = { - val inputs = boxesToSpend.map(box => Input(box.id, proofToSpend)) - val balanceToSpend = boxesToSpend.map(_.value).sum - balanceToReturn - - def creatingCandidate = new ErgoBoxCandidate(balanceToReturn, scriptToReturn, startHeight, replaceNewAssetStub(assets, inputs).toColl) - - val spendingOutput = if (balanceToSpend > 0) Some(new ErgoBoxCandidate(balanceToSpend, Constants.TrueLeaf, creationHeight = startHeight)) else None - val creatingOutput = if (balanceToReturn > 0) Some(creatingCandidate) else None - ErgoTransaction(inputs.toIndexedSeq, spendingOutput.toIndexedSeq ++ creatingOutput.toIndexedSeq) - } - - private def replaceNewAssetStub(assets: Seq[(TokenId, Long)], inputs: Seq[Input]): Seq[(TokenId, Long)] = { - def isNewAsset(tokenId: TokenId, value: Long): Boolean = tokenId == newAssetIdStub - - val (newAsset, spentAssets) = assets.partition((isNewAsset _).tupled) - newAsset.map(inputs.head.boxId.toTokenId -> _._2) ++ spentAssets - } - - def randomNewAsset: Seq[(TokenId, Long)] = Seq(newAssetIdStub -> randomLong()) - - def assetsWithRandom(boxes: Seq[ErgoBox]): Seq[(TokenId, Long)] = randomNewAsset ++ assetsByTokenId(boxes) - - val fakeInputs: IndexedSeq[Input] = IndexedSeq(Input(ADKey @@ Array.fill(32)(0: Byte), emptyProverResult)) - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/NodeViewFixture.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/NodeViewFixture.scala deleted file mode 100644 index 5127620226..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/NodeViewFixture.scala +++ /dev/null @@ -1,59 +0,0 @@ -package org.ergoplatform.utils.fixtures - -import akka.actor.{ActorRef, ActorSystem} -import akka.testkit.TestProbe -import org.ergoplatform.mining.emission.EmissionRules -import org.ergoplatform.nodeView.ErgoNodeViewRef -import org.ergoplatform.settings.{ErgoSettings, Parameters} -import org.ergoplatform.utils.NodeViewTestContext -import org.ergoplatform.wallet.utils.TestFileUtils - -import scala.concurrent.ExecutionContext - -/** This uses TestProbe to receive messages from actor. - * To make TestProbe work `defaultSender` implicit should be imported - */ -class NodeViewFixture(protoSettings: ErgoSettings, parameters: Parameters) extends NodeViewTestContext with TestFileUtils { self => - - implicit val actorSystem: ActorSystem = ActorSystem() - implicit val executionContext: ExecutionContext = actorSystem.dispatchers.lookup("scorex.executionContext") - implicit def ctx: NodeViewTestContext = this - - val nodeViewDir: java.io.File = createTempDir - @volatile var settings: ErgoSettings = protoSettings.copy(directory = nodeViewDir.getAbsolutePath) - val emission: EmissionRules = new EmissionRules(settings.chainSettings.monetary) - @volatile var nodeViewHolderRef: ActorRef = ErgoNodeViewRef(settings) - val testProbe = new TestProbe(actorSystem) - - /** This sender should be imported to make TestProbe work! */ - implicit val defaultSender: ActorRef = testProbe.testActor - - def apply[T](test: self.type => T): T = try test(self) finally stop() - - def startNodeViewHolder(): Unit = { - nodeViewHolderRef = ErgoNodeViewRef(settings) - } - - def stopNodeViewHolder(): Unit = { - actorSystem.stop(nodeViewHolderRef) - Thread.sleep(2000) - } - - /** Restarts nodeViewHolder and applies config override */ - def updateConfig(settingsOverride: ErgoSettings => ErgoSettings): Unit = { - stopNodeViewHolder() - settings = settingsOverride(settings) - startNodeViewHolder() - } - - def stop(): Unit = { - stopNodeViewHolder() - actorSystem.stop(testProbe.testActor) - actorSystem.terminate() - } -} - -object NodeViewFixture { - def apply(protoSettings: ErgoSettings, parameters: Parameters): NodeViewFixture = - new NodeViewFixture(protoSettings, parameters) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/SequentialAkkaFixture.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/SequentialAkkaFixture.scala deleted file mode 100644 index 7258cbb214..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/SequentialAkkaFixture.scala +++ /dev/null @@ -1,33 +0,0 @@ -package org.ergoplatform.utils.fixtures - -import java.util.concurrent.atomic.AtomicInteger - -import akka.actor.ActorSystem -import akka.testkit.{TestKit, ImplicitSender} -import org.scalatest.{Outcome, propspec} - -import scala.concurrent.Await -import scala.concurrent.duration.Duration - -object SequentialAkkaFixture { - val sysId = new AtomicInteger() -} - -trait SequentialAkkaFixture extends propspec.FixtureAnyPropSpec { - import SequentialAkkaFixture._ - type Fixture <: TestKit - type FixtureParam = Fixture - - class AkkaFixture extends TestKit(ActorSystem("WithIsoFix-%d".format(sysId.incrementAndGet()))) with ImplicitSender - - def createAkkaFixture(): Fixture - - override def withFixture(test: OneArgTest): Outcome = { - val sys = createAkkaFixture() - try { - test(sys) - } finally { - Await.result(sys.system.terminate(), Duration.Inf) - } - } -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/WalletFixture.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/WalletFixture.scala deleted file mode 100644 index 56a1d90f7a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/fixtures/WalletFixture.scala +++ /dev/null @@ -1,12 +0,0 @@ -package org.ergoplatform.utils.fixtures - -import org.ergoplatform.nodeView.wallet.ErgoWallet -import org.ergoplatform.settings.{ErgoSettings, Parameters} - -class WalletFixture( - settings: ErgoSettings, - params: Parameters, - getWallet: WalletFixture => ErgoWallet -) extends NodeViewFixture(settings, params) { - val wallet: ErgoWallet = getWallet(this) -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala deleted file mode 100644 index cfe35ca205..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ChainGenerator.scala +++ /dev/null @@ -1,197 +0,0 @@ -package org.ergoplatform.utils.generators - -import org.ergoplatform.Input -import org.ergoplatform.mining.difficulty.DifficultyAdjustment -import org.ergoplatform.modifiers.history.HeaderChain -import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, PoPowHeader} -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock, NonHeaderBlockSection} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.settings.Constants -import org.ergoplatform.utils.{BoxUtils, ErgoTestConstants} -import scorex.crypto.authds.{ADKey, SerializedAdProof} -import scorex.crypto.hash.Digest32 -import sigma.Colls -import sigmastate.eval._ -import sigmastate.helpers.TestingHelpers._ -import sigmastate.interpreter.{ContextExtension, ProverResult} - -import scala.util.Random - -trait ChainGenerator extends ErgoTestConstants { - - private def emptyProofs = SerializedAdProof @@ scorex.utils.Random.randomBytes(Random.nextInt(5000)) - - /** Generates a [[HeaderChain]] of given height starting from last block of the `history` - */ - def genHeaderChain(height: Int, - history: ErgoHistory, - diffBitsOpt: Option[Long], - useRealTs: Boolean): HeaderChain = { - val bestHeaderOpt = history.bestHeaderOpt - bestHeaderOpt - .flatMap(h => history.typedModifierById[Extension](h.extensionId)) - .map(ext => NipopowAlgos.unpackInterlinks(ext.fields).get) - .getOrElse(Seq.empty) - genHeaderChain( - height, - bestHeaderOpt, - history.difficultyCalculator, - diffBitsOpt = diffBitsOpt, - useRealTs = useRealTs - ) - } - - /** Generates a [[HeaderChain]] of given height starting from a given header - */ - final def genHeaderChain(height: Int, - prefixOpt: Option[Header] = None, - control: DifficultyAdjustment = defaultDifficultyControl, - extensionHash: Digest32 = EmptyDigest32, - diffBitsOpt: Option[Long], - useRealTs: Boolean): HeaderChain = - HeaderChain(headerStream(prefixOpt, control, extensionHash, diffBitsOpt, useRealTs).take(height + prefixOpt.size)) - - /** Generates a minimal [[HeaderChain]] that satisfies the given condition - */ - final def genHeaderChain(until: Seq[Header] => Boolean, - prefix: Option[Header], - control: DifficultyAdjustment, - diffBitsOpt: Option[Long], - useRealTs: Boolean): HeaderChain = { - val headers = headerStream(prefix, control, diffBitsOpt = diffBitsOpt, useRealTs = useRealTs) - val chain = Iterator.from(prefix.size).map(size => headers.take(size)).find(until).get - HeaderChain(chain) - } - - def popowHeaderChain(chain: HeaderChain): Seq[PoPowHeader] = { - chain.headers.foldLeft((Seq.empty[PoPowHeader], None: Option[PoPowHeader])) { - case ((acc, bestHeaderOpt), h) => - val links = if (bestHeaderOpt.isEmpty) { - Seq(scorex.util.bytesToId(Array.fill(32)(0: Byte))) - } else { - nipopowAlgos.updateInterlinks( - bestHeaderOpt.map(_.header), - bestHeaderOpt.map(ph => nipopowAlgos.interlinksToExtension(ph.interlinks).toExtension(ph.id)) - ) - } - val interlinkProof = NipopowAlgos.proofForInterlinkVector(ExtensionCandidate(NipopowAlgos.packInterlinks(links))) - .getOrElse(throw new Error(s"Failed to build interlink proof.")) - val poPowH = PoPowHeader(h, links, interlinkProof) - (acc :+ poPowH, Some(poPowH)) - }._1 - } - - private def headerStream(prefix: Option[Header], - control: DifficultyAdjustment, - extensionHash: Digest32 = EmptyDigest32, - diffBitsOpt: Option[Long], - useRealTs: Boolean): Stream[Header] = { - val firstHeader = nextHeader(prefix, control, extensionHash, diffBitsOpt = diffBitsOpt, useRealTs = useRealTs) - lazy val headers: Stream[Header] = firstHeader #:: headers.map(cur => - nextHeader(Option(cur), control, extensionHash, diffBitsOpt = diffBitsOpt, useRealTs = useRealTs)) - prefix.toSeq ++: headers - } - - def nextHeader(prev: Option[Header], - control: DifficultyAdjustment, - extensionHash: Digest32 = EmptyDigest32, - tsOpt: Option[Long] = None, - diffBitsOpt: Option[Long] = None, - useRealTs: Boolean): Header = - powScheme.prove( - prev, - Header.InitialVersion, - diffBitsOpt.getOrElse(settings.chainSettings.initialNBits), - EmptyStateRoot, - EmptyDigest32, - EmptyDigest32, - tsOpt.getOrElse(prev.map(_.timestamp + control.desiredInterval.toMillis) - .getOrElse(if (useRealTs) System.currentTimeMillis() else 0)), - extensionHash, - Array.fill(3)(0: Byte), - defaultMinerSecretNumber - ).get - - def genChain(height: Int): Seq[ErgoFullBlock] = - blockStream(None).take(height) - - def genChain(height: Int, prefix: ErgoFullBlock): Seq[ErgoFullBlock] = - blockStream(Option(prefix)).take(height + 1) - - def genChain(height: Int, - history: ErgoHistory, - blockVersion: Header.Version = Header.InitialVersion, - nBits: Long = settings.chainSettings.initialNBits, - extension: ExtensionCandidate = defaultExtension): Seq[ErgoFullBlock] = { - val prefix = history.bestFullBlockOpt - blockStream(prefix, blockVersion, nBits, extension).take(height + prefix.size) - } - - protected def blockStream(prefix: Option[ErgoFullBlock], - blockVersion: Header.Version = Header.InitialVersion, - nBits: Long = settings.chainSettings.initialNBits, - extension: ExtensionCandidate = defaultExtension): Stream[ErgoFullBlock] = { - val proof = ProverResult(Array(0x7c.toByte), ContextExtension.empty) - val inputs = IndexedSeq(Input(ADKey @@ Array.fill(32)(0: Byte), proof)) - val minimalAmount = BoxUtils.minimalErgoAmountSimulated(Constants.TrueLeaf, Colls.emptyColl, Map(), parameters) - val outputs = IndexedSeq(testBox(minimalAmount, Constants.TrueLeaf, creationHeight = startHeight)) - - def txs = Seq(ErgoTransaction(inputs, outputs)) - - lazy val blocks: Stream[ErgoFullBlock] = - nextBlock(prefix, txs, extension, blockVersion, nBits) #:: - blocks.zip(Stream.from(2)).map { case (prev, _) => - nextBlock(Option(prev), txs, extension, blockVersion, nBits) - } - prefix ++: blocks - } - - def nextBlock(prev: Option[ErgoFullBlock], - txs: Seq[ErgoTransaction], - extension: ExtensionCandidate, - blockVersion: Header.Version = Header.InitialVersion, - nBits: Long = settings.chainSettings.initialNBits): ErgoFullBlock = { - val interlinks = prev.toSeq.flatMap(x => - nipopowAlgos.updateInterlinks(x.header, NipopowAlgos.unpackInterlinks(x.extension.fields).get)) - val validExtension = extension ++ nipopowAlgos.interlinksToExtension(interlinks) - powScheme.proveBlock( - prev.map(_.header), - blockVersion, - nBits, - EmptyStateRoot, - emptyProofs, - txs, - Math.max(System.currentTimeMillis(), prev.map(_.header.timestamp + 1).getOrElse(System.currentTimeMillis())), - validExtension, - Array.fill(3)(0: Byte), - defaultMinerSecretNumber - ).get - } - - def applyHeaderChain(historyIn: ErgoHistory, chain: HeaderChain): ErgoHistory = { - var history = historyIn - chain.headers.foreach { header => - history = history.append(header).get._1 - } - history - } - - def applyChain(historyIn: ErgoHistory, blocks: Seq[ErgoFullBlock]): ErgoHistory = { - def appendOrPass(mod: BlockSection, history: ErgoHistory) = - if (history.contains(mod)) history else history.append(mod).get._1 - blocks.foldLeft(historyIn) { (history, block) => - val historyWithBlockHeader = appendOrPass(block.header, history) - val historyWithTxs = appendOrPass(block.blockTransactions, historyWithBlockHeader) - val historyWithExtension = appendOrPass(block.extension, historyWithTxs) - block.adProofs.map(p => appendOrPass(p, historyWithExtension)).getOrElse(historyWithExtension) - } - } - - def applyBlock(historyIn: ErgoHistory, block: ErgoFullBlock): ErgoHistory = applyChain(historyIn, Seq(block)) - - def applySection(historyIn: ErgoHistory, section: NonHeaderBlockSection): ErgoHistory = historyIn.append(section).get._1 - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala deleted file mode 100644 index ad49b7557a..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoGenerators.scala +++ /dev/null @@ -1,216 +0,0 @@ -package org.ergoplatform.utils.generators - -import com.google.common.primitives.Shorts -import org.bouncycastle.util.BigIntegers -import org.ergoplatform.mining.difficulty.DifficultySerializer -import org.ergoplatform.mining.{AutolykosSolution, genPk, q} -import org.ergoplatform.modifiers.history.ADProofs -import org.ergoplatform.modifiers.history.extension.Extension -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.{NipopowProof, PoPowParams} -import org.ergoplatform.network.ModePeerFeature -import org.ergoplatform.nodeView.history.{ErgoSyncInfo, ErgoSyncInfoV1, ErgoSyncInfoV2} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsUpdate, ValidationRules} -import org.ergoplatform.utils.ErgoTestConstants -import org.ergoplatform.validation.{ChangedRule, DisabledRule, EnabledRule, ReplacedRule} -import org.ergoplatform.wallet.utils.Generators -import org.scalacheck.Arbitrary.arbByte -import org.scalacheck.{Arbitrary, Gen} -import org.scalatest.matchers.should.Matchers -import scorex.crypto.authds.{ADDigest, SerializedAdProof} -import scorex.crypto.hash.Digest32 -import scorex.testkit.generators.CoreGenerators -import sigmastate.Values.ErgoTree -import sigmastate.crypto.CryptoConstants.EcPointType -import sigmastate.crypto.DLogProtocol.{DLogProverInput, ProveDlog} -import sigmastate.crypto.{CryptoConstants, DiffieHellmanTupleProverInput, ProveDHTuple} -import sigmastate.interpreter.ProverResult - -import scala.util.Random - -trait ErgoGenerators extends CoreGenerators with ChainGenerator with Generators with Matchers with ErgoTestConstants { - - lazy val trueLeafGen: Gen[ErgoTree] = Gen.const(Constants.TrueLeaf) - lazy val falseLeafGen: Gen[ErgoTree] = Gen.const(Constants.FalseLeaf) - - lazy val smallPositiveInt: Gen[Int] = Gen.choose(1, 5) - - lazy val noProofGen: Gen[ProverResult] = - Gen.const(emptyProverResult) - - lazy val dlogSecretWithPublicImageGen: Gen[(DLogProverInput, ProveDlog)] = for { - secret <- genBytes(32).map(seed => BigIntegers.fromUnsignedByteArray(seed)) - dlpi = DLogProverInput(secret) - } yield (dlpi, dlpi.publicImage) - - lazy val dhtSecretWithPublicImageGen: Gen[(DiffieHellmanTupleProverInput, ProveDHTuple)] = for { - secret <- genBytes(32).map(seed => BigIntegers.fromUnsignedByteArray(seed)) - g <- genECPoint - h <- genECPoint - u = CryptoConstants.dlogGroup.exponentiate(g, secret) - v = CryptoConstants.dlogGroup.exponentiate(h, secret) - dhtpi = DiffieHellmanTupleProverInput(secret, ProveDHTuple(g, h, u, v)) - } yield (dhtpi, dhtpi.publicImage) - - lazy val proveDlogGen: Gen[ProveDlog] = for { - seed <- genBytes(32) - } yield DLogProverInput(BigIntegers.fromUnsignedByteArray(seed)).publicImage - - lazy val proveDlogTreeGen: Gen[ErgoTree] = proveDlogGen.map(_.toSigmaProp) - - lazy val ergoPropositionGen: Gen[ErgoTree] = Gen.oneOf(trueLeafGen, falseLeafGen, proveDlogTreeGen) - - lazy val positiveIntGen: Gen[Int] = Gen.choose(1, Int.MaxValue) - - lazy val ergoSyncInfoV1Gen: Gen[ErgoSyncInfoV1] = for { - ids <- Gen.nonEmptyListOf(modifierIdGen).map(_.take(ErgoSyncInfo.MaxBlockIds)) - } yield ErgoSyncInfoV1(ids) - - lazy val ergoSyncInfoV2Gen: Gen[ErgoSyncInfoV2] = for { - hds <- Gen.nonEmptyListOf(invalidHeaderGen).map(_.take(5)) - } yield ErgoSyncInfoV2(hds) - - lazy val digest32Gen: Gen[Digest32] = { - val x = Digest32 @@ genBytes(32) - x - } - - lazy val stateRootGen: Gen[ADDigest] = { - val x = ADDigest @@ genBytes(Constants.ModifierIdSize + 1) - x - } - - lazy val serializedAdProofGen: Gen[SerializedAdProof] = { - val x = SerializedAdProof @@ genBoundedBytes(32, 32 * 1024) - x - } - - def genSecureBoundedBytes(minSize: Int, maxSize: Int): Gen[Array[Byte]] = - Gen.choose(minSize, maxSize).flatMap { - scorex.util.Random.randomBytes - } - - def extensionKvGen(keySize: Int, valuesSize: Int): Gen[(Array[Byte], Array[Byte])] = for { - key <- genSecureBoundedBytes(keySize, keySize) - value <- if (key.head == 0) genSecureBoundedBytes(4, 4) else genSecureBoundedBytes(valuesSize, valuesSize) - } yield (key, value) - - lazy val extensionGen: Gen[Extension] = for { - headerId <- modifierIdGen - mandatoryElements <- Gen.mapOf(extensionKvGen(Extension.FieldKeySize, Extension.FieldValueMaxSize)) - } yield { - val me = mandatoryElements - .map(kv => Shorts.fromByteArray(kv._1) -> kv._2) - .map(kv => Shorts.toByteArray(kv._1) -> kv._2) - Extension(headerId, me.toSeq) - } - - lazy val genECPoint: Gen[EcPointType] = genBytes(32).map(b => genPk(BigInt(b).mod(q))) - - lazy val powSolutionGen: Gen[AutolykosSolution] = for { - pk <- genECPoint - w <- genECPoint - n <- genBytes(8) - d <- Arbitrary.arbitrary[BigInt].map(_.mod(q - 1) + 1) - } yield AutolykosSolution(pk, w, n, d) - - /** - * Generates required difficulty in interval [1, 2^^255] - **/ - lazy val requiredDifficultyGen: Gen[BigInt] = Arbitrary.arbitrary[BigInt].map(_.mod(BigInt(2).pow(255)).abs + 1) - - /* - TODO: this generator is used sometimes to construct a full block. A generator for the latter is not generating - a proper extension section for a beginning of a voting epoch (network parameter values should be in the extension - in this case. Currently we're fixing it here with filtering out heights corresponding to the beginning of voting - epochs. A more careful solution would be to implement proper generators. - */ - lazy val invalidHeaderGen: Gen[Header] = for { - version <- Arbitrary.arbitrary[Byte] - parentId <- modifierIdGen - stateRoot <- stateRootGen - adRoot <- digest32Gen - transactionsRoot <- digest32Gen - requiredDifficulty <- requiredDifficultyGen - height <- Gen.choose(1, Int.MaxValue).retryUntil(_ % settings.chainSettings.voting.votingLength != 0) - powSolution <- powSolutionGen - timestamp <- positiveLongGen - extensionHash <- digest32Gen - } yield Header( - version, - parentId, - adRoot, - stateRoot, - transactionsRoot, - timestamp, - DifficultySerializer.encodeCompactBits(requiredDifficulty), - height, - extensionHash, - powSolution, - Array.fill(3)(0: Byte), - None - ) - - /** - * Header generator with default miner pk in pow solution - */ - lazy val defaultHeaderGen: Gen[Header] = invalidHeaderGen.map { h => - h.copy(powSolution = h.powSolution.copy(pk = defaultMinerPkPoint)) - } - - lazy val randomADProofsGen: Gen[ADProofs] = for { - headerId <- modifierIdGen - proof <- serializedAdProofGen - } yield ADProofs(headerId, proof) - - lazy val emptyMemPoolGen: Gen[ErgoMemPool] = - Gen.resultOf({ _: Unit => ErgoMemPool.empty(settings) })(Arbitrary(Gen.const(()))) - - lazy val modeFeatureGen: Gen[ModePeerFeature] = for { - stateTypeCode <- Gen.choose(StateType.Utxo.stateTypeCode, StateType.Utxo.stateTypeCode) - popowSuffix <- Gen.choose(1, 10) - blocksToKeep <- Gen.choose(1, 100000) - } yield ModePeerFeature( - StateType.fromCode(stateTypeCode), - Random.nextBoolean(), - if (Random.nextBoolean()) Some(popowSuffix) else None, - blocksToKeep) - - lazy val ergoValidationSettingsUpdateGen: Gen[ErgoValidationSettingsUpdate] = for { - n <- Gen.choose(1, 200) - disabledRules = ValidationRules.rulesSpec.filter(_._2.mayBeDisabled).keys.take(n).toSeq - replacedRuleCode <- Gen.choose(org.ergoplatform.validation.ValidationRules.FirstRuleId, Short.MaxValue) - changedRuleValue <- genBoundedBytes(0, 127) - statuses <- Gen.listOf(Gen.oneOf(DisabledRule, EnabledRule, ReplacedRule(replacedRuleCode), ChangedRule(changedRuleValue))) - statusUpdates = org.ergoplatform.validation.ValidationRules.ruleSpecs.take(statuses.size).map(_.id).zip(statuses) - } yield ErgoValidationSettingsUpdate(disabledRules, statusUpdates) - - lazy val ergoValidationSettingsGen: Gen[ErgoValidationSettings] = ergoValidationSettingsUpdateGen - .map(u => ErgoValidationSettings.initial.updated(u)) - - /** Random long from 1 to maximum - 1 - * - * @param maximum should be positive - */ - def randomLong(maximum: Long = Long.MaxValue): Long = { - if (maximum < 3) 1 else Math.abs(Random.nextLong()) % (maximum - 2) + 1 - } - - lazy val poPowProofGen: Gen[NipopowProof] = for { - m <- Gen.chooseNum(1, 128) - k <- Gen.chooseNum(1, 128) - proof <- validNiPoPowProofGen(m, k) - } yield proof - - def validNiPoPowProofGen(m: Int, k: Int): Gen[NipopowProof] = for { - mulM <- Gen.chooseNum(1, 20) - } yield { - val chain = genHeaderChain(m * mulM + k, diffBitsOpt = None, useRealTs = false) - val popowChain = popowHeaderChain(chain) - val params = PoPowParams(m, k, continuous = false) - nipopowAlgos.prove(popowChain)(params).get - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala deleted file mode 100644 index 978617e43d..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala +++ /dev/null @@ -1,358 +0,0 @@ -package org.ergoplatform.utils.generators - -import org.ergoplatform.ErgoBox.TokenId -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.nodeView.state.{BoxHolder, ErgoStateContext, VotingData} -import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionSigningRequest} -import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, WalletTransaction} -import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey} -import org.ergoplatform.settings.Parameters._ -import org.ergoplatform.settings.{Constants, Parameters} -import org.ergoplatform.utils.{BoxUtils, RandomLike, RandomWrapper} -import org.ergoplatform.sdk.wallet.Constants.MaxAssetsPerBox -import org.ergoplatform.wallet.interpreter.TransactionHintsBag -import org.ergoplatform.wallet.utils.Generators -import org.ergoplatform._ -import org.ergoplatform.wallet.Constants.ScanId -import org.scalacheck.Gen -import scorex.crypto.hash.Blake2b256 -import scorex.db.ByteArrayWrapper -import scorex.util.encode.Base16 -import sigmastate.Values.ErgoTree -import sigmastate.crypto.DLogProtocol.ProveDlog -import sigmastate.eval.Extensions._ -import sigmastate.eval._ -import sigmastate.helpers.TestingHelpers._ - -import scala.collection.JavaConverters._ -import scala.collection.mutable -import scala.util.Random - -trait ErgoTransactionGenerators extends ErgoGenerators with Generators { - - protected implicit val addressEncoder: ErgoAddressEncoder = - ErgoAddressEncoder(settings.chainSettings.addressPrefix) - - val creationHeightGen: Gen[Int] = Gen.choose(0, Int.MaxValue / 2) - - lazy val ergoBoxCandidateGen: Gen[ErgoBoxCandidate] = for { - h <- creationHeightGen - prop <- trueLeafGen - ar <- additionalRegistersGen - tokens <- additionalTokensGen - value <- validValueGen - } yield new ErgoBoxCandidate(value, prop, h, tokens.toColl, ar) - - def ergoAddressGen: Gen[ErgoAddress] = proveDlogGen.map(P2PKAddress.apply) - - def ergoBoxCandidateGen(prop: ProveDlog): Gen[ErgoBoxCandidate] = for { - h <- creationHeightGen - ar <- additionalRegistersGen - tokens <- additionalTokensGen - value <- validValueGen - } yield new ErgoBoxCandidate(value, prop, h, tokens.toColl, ar) - - lazy val ergoBoxGenNoProp: Gen[ErgoBox] = ergoBoxGen(propGen = trueLeafGen) - - def ergoBoxGenForTokens(tokens: Seq[(TokenId, Long)], - propositionGen: Gen[ErgoTree]): Gen[ErgoBox] = { - ergoBoxGen(propGen = propositionGen, tokensGen = Gen.oneOf(tokens, tokens), heightGen = ErgoHistory.EmptyHistoryHeight) - } - - def unspendableErgoBoxGen(minValue: Long = parameters.minValuePerByte * 200, - maxValue: Long = coinsTotal): Gen[ErgoBox] = { - ergoBoxGen(propGen = falseLeafGen, valueGenOpt = Some(Gen.choose(minValue, maxValue))) - } - - lazy val inputGen: Gen[Input] = for { - boxId <- boxIdGen - spendingProof <- noProofGen - } yield Input(boxId, spendingProof) - - lazy val dataInputGen: Gen[DataInput] = for { - boxId <- boxIdGen - } yield DataInput(boxId) - - lazy val reallySmallInt: Gen[Int] = Gen.choose(0, 3) - - lazy val invalidErgoTransactionGen: Gen[ErgoTransaction] = for { - from: IndexedSeq[Input] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, inputGen).map(_.toIndexedSeq)) - dataInputs: IndexedSeq[DataInput] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, dataInputGen).map(_.toIndexedSeq)) - to: IndexedSeq[ErgoBoxCandidate] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, ergoBoxCandidateGen).map(_.toIndexedSeq)) - } yield ErgoTransaction(from, dataInputs, to) - - def invalidErgoTransactionGen(prop: ProveDlog): Gen[ErgoTransaction] = for { - from: IndexedSeq[Input] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, inputGen).map(_.toIndexedSeq)) - dataInputs: IndexedSeq[DataInput] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, dataInputGen).map(_.toIndexedSeq)) - to: IndexedSeq[ErgoBoxCandidate] <- reallySmallInt.flatMap(i => Gen.listOfN(i + 1, ergoBoxCandidateGen(prop)).map(_.toIndexedSeq)) - } yield ErgoTransaction(from, dataInputs, to) - - lazy val walletTransactionGen: Gen[WalletTransaction] = for { - tx <- invalidErgoTransactionGen - inclusionHeight <- Gen.posNum[Int] - scanId <- ScanId @@ Gen.posNum[Short] - } yield WalletTransaction(tx, inclusionHeight, Seq(scanId)) - - def walletTransactionForScanGen(scanId: ScanId): Gen[WalletTransaction] = for { - tx <- invalidErgoTransactionGen - inclusionHeight <- Gen.posNum[Int] - } yield WalletTransaction(tx, inclusionHeight, Seq(scanId)) - - def augWalletTransactionForScanGen(scanId: ScanId, includeUnconfirmed: Boolean): Gen[AugWalletTransaction] = for { - tx <- walletTransactionForScanGen(scanId) - numConfirmation <- if (includeUnconfirmed) Gen.const(0) else Gen.posNum[Int] - } yield AugWalletTransaction(tx, numConfirmation) - - lazy val augWalletTransactionGen: Gen[AugWalletTransaction] = for { - tx <- walletTransactionGen - numConfirmation <- Gen.posNum[Int] - } yield AugWalletTransaction(tx, numConfirmation) - - /** - * Generates a transaction that is valid if correct boxes were provided. - * Generated transaction may still be invalid, if: - * - default prover does not know how to sign at least one input - * - number of assets exceeds MaxAssetsPerBox - */ - def validUnsignedTransactionFromBoxes(boxesToSpend: IndexedSeq[ErgoBox], - rnd: RandomLike = new RandomWrapper, - issueNew: Boolean = true, - outputsProposition: ErgoTree = Constants.TrueLeaf, - dataBoxes: IndexedSeq[ErgoBox] = IndexedSeq()): UnsignedErgoTransaction = { - require(boxesToSpend.nonEmpty, "At least one box is needed to generate a transaction") - - val inputSum = boxesToSpend.map(_.value).reduce(Math.addExact(_, _)) - val assetsMap: mutable.Map[ByteArrayWrapper, Long] = - mutable.Map(boxesToSpend.flatMap(_.additionalTokens.toArray).map { case (bs, amt) => - ByteArrayWrapper(bs.toArray) -> amt - }: _*) - - //randomly creating a new asset - if (rnd.nextBoolean() && issueNew) { - assetsMap.put(ByteArrayWrapper(boxesToSpend.head.id), rnd.nextInt(Int.MaxValue)) - } - - val minValue = BoxUtils.sufficientAmount(extendedParameters) - - require(inputSum >= minValue) - val inputsCount = boxesToSpend.size - val maxOutputs = Math.min(Short.MaxValue, inputSum / minValue).toInt - val outputsCount = Math.min(maxOutputs, Math.max(inputsCount + 1, rnd.nextInt(inputsCount * 2))) - require(outputsCount > 0, s"outputs count is not positive: $outputsCount") - - require(minValue * outputsCount <= inputSum) - val outputPreamounts = (1 to outputsCount).map(_ => minValue).toBuffer - - var remainder = inputSum - minValue * outputsCount - do { - val idx = Random.nextInt(outputsCount) - if (remainder < inputSum / inputsCount) { - outputPreamounts.update(idx, outputPreamounts(idx) + remainder) - remainder = 0 - } else { - val value = Math.abs(rnd.nextLong()) % (remainder / outputsCount) - outputPreamounts.update(idx, outputPreamounts(idx) + value) - remainder = remainder - value - } - } while (remainder > 0) - - val outputAmounts = outputPreamounts.toIndexedSeq - - val tokenAmounts: mutable.IndexedSeq[mutable.Map[ByteArrayWrapper, Long]] = - mutable.IndexedSeq.fill(outputsCount)(mutable.Map[ByteArrayWrapper, Long]()) - - var availableTokenSlots = outputsCount * MaxAssetsPerBox - - if (assetsMap.nonEmpty) { - do { - val in = assetsMap.head - val outIdx = Stream.from(1, 1).map(_ => rnd.nextInt(tokenAmounts.size)) - .find(idx => tokenAmounts(idx).size < MaxAssetsPerBox).get - val out = tokenAmounts(outIdx) - val contains = out.contains(in._1) - - val amt = if (in._2 == 1 || (availableTokenSlots < assetsMap.size * 2 && !contains) || rnd.nextBoolean()) { - in._2 - } else { - Math.max(1, Math.min((rnd.nextDouble() * in._2).toLong, in._2)) - } - - if (amt == in._2) assetsMap.remove(in._1) else assetsMap.update(in._1, in._2 - amt) - if (contains) { - val outAmt = out(in._1) - out.update(in._1, outAmt + amt) - } else { - availableTokenSlots = availableTokenSlots - 1 - out.update(in._1, amt) - } - tokenAmounts(outIdx) = out - } while (assetsMap.nonEmpty && availableTokenSlots > 0) - } - - val newBoxes = outputAmounts.zip(tokenAmounts.toIndexedSeq).map { case (amt, tokens) => - val normalizedTokens = tokens.toSeq.map(t => t._1.data.toTokenId -> t._2) - testBox(amt, outputsProposition, 0, normalizedTokens) - } - val inputs = boxesToSpend.map(b => Input(b.id, emptyProverResult)) - val dataInputs = dataBoxes.map(b => DataInput(b.id)) - val unsignedTx = UnsignedErgoTransaction(inputs, dataInputs, newBoxes) - require(unsignedTx.dataInputs.length == dataBoxes.length, s"${unsignedTx.dataInputs.length} == ${dataBoxes.length}") - unsignedTx - } - - def validTransactionFromBoxes(boxesToSpend: IndexedSeq[ErgoBox], - rnd: RandomLike = new RandomWrapper, - issueNew: Boolean = true, - outputsProposition: ErgoTree = Constants.TrueLeaf, - stateCtxOpt: Option[ErgoStateContext] = None, - dataBoxes: IndexedSeq[ErgoBox] = IndexedSeq()): ErgoTransaction = { - val unsignedTx = validUnsignedTransactionFromBoxes(boxesToSpend, rnd, issueNew, outputsProposition, dataBoxes) - defaultProver.sign(unsignedTx, boxesToSpend, dataBoxes, stateCtxOpt.getOrElse(emptyStateContext)) - .map(ErgoTransaction.apply) - .getOrElse { - log.debug(s"Going to generate a transaction with incorrect spending proofs: $unsignedTx") - ErgoTransaction(boxesToSpend.map(b => Input(b.id, emptyProverResult)), unsignedTx.dataInputs, unsignedTx.outputs) - } - } - - def disperseTokens(inputsCount: Int, tokensCount: Byte): Gen[IndexedSeq[Seq[(TokenId, Long)]]] = { - val tokensDistribution = mutable.IndexedSeq.fill(inputsCount)(Seq[(TokenId, Long)]()) - (1 to tokensCount).foreach { i => - val (id, amt) = Blake2b256(s"$i" + Random.nextString(5)).toTokenId -> (Random.nextInt(Int.MaxValue).toLong + 100) - val idx = i % tokensDistribution.size - val s = tokensDistribution(idx) - tokensDistribution(idx) = s :+ (id -> amt) - } - tokensDistribution.ensuring(_.forall(_.forall(_._2 > 0))) - } - - def boxesGenTemplate(minAssets: Int, - maxAssets: Int, - minInputs: Int, - maxInputs: Int, - propositionGen: Gen[ErgoTree]): Gen[(IndexedSeq[ErgoBox], ErgoTree)] = for { - inputsCount <- Gen.choose(minInputs, maxInputs) - tokensCount <- Gen.choose( - minAssets, - Math.max(maxAssets, inputsCount)) - tokensDistribution <- disperseTokens(inputsCount, tokensCount.toByte) - from <- Gen.sequence(tokensDistribution.map(tokens => ergoBoxGenForTokens(tokens, propositionGen))) - prop <- propositionGen - } yield from.asScala.toIndexedSeq -> prop - - def validErgoTransactionGenTemplate(minAssets: Int, - maxAssets: Int = -1, - maxInputs: Int = 100, - propositionGen: Gen[ErgoTree] = trueLeafGen - ): Gen[(IndexedSeq[ErgoBox], ErgoTransaction)] = { - boxesGenTemplate(minAssets, maxAssets, maxInputs, maxInputs, propositionGen).map { case (boxes, prop) => - val tx = validTransactionFromBoxes(boxes, outputsProposition = prop) - boxes -> tx - } - } - - def validUnsignedErgoTransactionGenTemplate(minAssets: Int, - maxAssets: Int, - maxInputs: Int, - propositionGen: Gen[ErgoTree]): Gen[(IndexedSeq[ErgoBox], UnsignedErgoTransaction)] = { - boxesGenTemplate(minAssets, maxAssets, maxInputs, maxInputs, propositionGen).map { case (boxes, prop) => - val utx = validUnsignedTransactionFromBoxes(boxes, outputsProposition = prop) - boxes -> utx - } - } - - def validUnsignedErgoTransactionGen(prop: ErgoTree*): Gen[(IndexedSeq[ErgoBox], UnsignedErgoTransaction)] = - validUnsignedErgoTransactionGenTemplate(minAssets = 0, maxAssets = 5, maxInputs = 10, propositionGen = Gen.oneOf(prop)) - - lazy val validUnsignedErgoTransactionGen: Gen[(IndexedSeq[ErgoBox], UnsignedErgoTransaction)] = - validUnsignedErgoTransactionGenTemplate(minAssets = 0, maxAssets = 5, maxInputs = 10, propositionGen = trueLeafGen) - - lazy val validErgoTransactionGen: Gen[(IndexedSeq[ErgoBox], ErgoTransaction)] = validErgoTransactionGenTemplate(minAssets = 0) - lazy val validErgoTransactionWithAssetsGen: Gen[(IndexedSeq[ErgoBox], ErgoTransaction)] = - validErgoTransactionGenTemplate(minAssets = 1) - - def boxesHolderGenOfSize(numBoxes:Int): Gen[BoxHolder] = Gen.listOfN(numBoxes, ergoBoxGenForTokens(Seq(), trueLeafGen)) - .map(l => BoxHolder(l)) - - lazy val boxesHolderGen: Gen[BoxHolder] = Gen.listOfN(2000, ergoBoxGenForTokens(Seq(), trueLeafGen)) - .map(l => BoxHolder(l)) - - lazy val invalidBlockTransactionsGen: Gen[BlockTransactions] = for { - headerId <- modifierIdGen - txs <- Gen.nonEmptyListOf(invalidErgoTransactionGen) - } yield BlockTransactions(headerId, Header.InitialVersion, txs.foldLeft(Seq.empty[ErgoTransaction])((acc, tx) => - if ((acc :+ tx).map(_.size).sum < (Parameters.MaxBlockSizeDefault - 150)) acc :+ tx else acc)) - - def invalidBlockTransactionsGen(prop: ProveDlog, txQty: Int): Gen[BlockTransactions] = for { - headerId <- modifierIdGen - txs <- Gen.listOfN(txQty, invalidErgoTransactionGen(prop)) - } yield BlockTransactions(headerId, Header.InitialVersion, txs.foldLeft(Seq.empty[ErgoTransaction])((acc, tx) => - if ((acc :+ tx).map(_.size).sum < (Parameters.MaxBlockSizeDefault - 150)) acc :+ tx else acc)) - - lazy val invalidErgoFullBlockGen: Gen[ErgoFullBlock] = for { - header <- defaultHeaderGen - txs <- invalidBlockTransactionsGen - extension <- extensionGen - proof <- randomADProofsGen - } yield ErgoFullBlock(header, txs, extension, Some(proof)) - - def invalidErgoFullBlockGen(prop: ProveDlog, txQty: Int): Gen[ErgoFullBlock] = for { - header <- defaultHeaderGen - txs <- invalidBlockTransactionsGen(prop, txQty) - extension <- extensionGen - proof <- randomADProofsGen - } yield ErgoFullBlock(header, txs, extension, Some(proof)) - - lazy val paramVoteGen: Gen[Byte] = for { - paramVote <- Gen.oneOf(Seq(NoParameter, StorageFeeFactorIncrease, MinValuePerByteIncrease)) - } yield paramVote - - lazy val paramVotesGen: Gen[Array[Byte]] = for { - firstVote <- paramVoteGen - } yield Array(firstVote, NoParameter, NoParameter) - - lazy val ergoStateContextGen: Gen[ErgoStateContext] = for { - size <- Gen.choose(0, Constants.LastHeadersInContext + 3) - stateRoot <- stateRootGen - blocks <- Gen.listOfN(size, invalidErgoFullBlockGen) - votes <- Gen.listOfN(size, paramVotesGen) - } yield { - blocks match { - case _ :: _ => - val sc = new ErgoStateContext(Seq(), None, startDigest, parameters, validationSettingsNoIl, VotingData.empty) - blocks.foldLeft(sc -> 1) { case ((c, h), b) => - val block = b.copy(header = b.header.copy(height = h, votes = votes(h - 1))) - c.appendFullBlock(block).get -> (h + 1) - }._1 - case _ => - ErgoStateContext.empty(stateRoot, settings, parameters) - } - } - - def transactionSigningRequestGen(includeInputs: Boolean): Gen[TransactionSigningRequest] = for { - (secret, pubKey) <- dlogSecretWithPublicImageGen - (secretDh, _) <- dhtSecretWithPublicImageGen - (inputBoxes, utx) <- validUnsignedErgoTransactionGen(pubKey) - inputBoxesEncoded = inputBoxes.map(b => Base16.encode(b.bytes)) - secretSeq = Seq(ExternalSecret(DlogSecretKey(secret)), ExternalSecret(DhtSecretKey(secretDh))) - } yield TransactionSigningRequest(utx, TransactionHintsBag.empty, secretSeq, - if (includeInputs) Some(inputBoxesEncoded) else None, None) - - def transactionSigningRequestGen(utxoSet: WrappedUtxoState): Gen[TransactionSigningRequest] = Gen.const { - val inputBoxes = utxoSet.takeBoxes(3).toIndexedSeq - - val utx = UnsignedErgoTransaction(inputBoxes.map(b => new UnsignedInput(b.id)), inputBoxes) - val coin = Random.nextBoolean() - val inputBoxesEncoded = inputBoxes.map(b => Base16.encode(b.bytes)) - - TransactionSigningRequest(utx, TransactionHintsBag.empty, Seq.empty, if (coin) Some(inputBoxesEncoded) else None, None) - } - -} - -object ErgoTransactionGenerators extends ErgoTransactionGenerators diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala deleted file mode 100644 index b579b50cd7..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/ValidBlocksGenerators.scala +++ /dev/null @@ -1,247 +0,0 @@ -package org.ergoplatform.utils.generators - -import org.ergoplatform.ErgoBox -import org.ergoplatform.mining.CandidateGenerator -import org.ergoplatform.modifiers.ErgoFullBlock -import org.ergoplatform.modifiers.history.extension.{Extension, ExtensionCandidate} -import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.modifiers.history.popow.NipopowAlgos -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.state._ -import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState -import org.ergoplatform.settings.{Algos, Constants, ErgoSettings, Parameters} -import org.ergoplatform.utils.{LoggingUtil, RandomLike, RandomWrapper} -import org.ergoplatform.wallet.utils.TestFileUtils -import org.scalatest.matchers.should.Matchers -import scorex.core.VersionTag -import scorex.crypto.authds.avltree.batch.Remove -import scorex.crypto.authds.ADDigest -import scorex.db.ByteArrayWrapper -import scorex.testkit.TestkitHelpers - -import scala.annotation.tailrec -import scala.collection.mutable -import scala.util.{Failure, Random, Success} - -trait ValidBlocksGenerators - extends TestkitHelpers with TestFileUtils with Matchers with ChainGenerator with ErgoTransactionGenerators { - - def createUtxoState(settings: ErgoSettings): (UtxoState, BoxHolder) = { - ErgoState.generateGenesisUtxoState(createTempDir, settings) - } - - def createUtxoState(bh: BoxHolder, parameters: Parameters): UtxoState = - UtxoState.fromBoxHolder(bh, None, createTempDir, settings, parameters) - - def createDigestState(version: VersionTag, digest: ADDigest): DigestState = - DigestState.create(Some(version), Some(digest), createTempDir, settings) - - def validTransactionsFromBoxHolder(boxHolder: BoxHolder): (Seq[ErgoTransaction], BoxHolder) = - validTransactionsFromBoxHolder(boxHolder, new RandomWrapper) - - protected def validTransactionsFromBoxes(sizeLimit: Int, - stateBoxesIn: Seq[ErgoBox], - rnd: RandomLike): (Seq[ErgoTransaction], Seq[ErgoBox]) = { - validTransactionsFromBoxes(sizeLimit, stateBoxesIn, Seq(), rnd) - } - - /** @param sizeLimit maximum transactions size in bytes */ - protected def validTransactionsFromBoxes(sizeLimit: Int, - stateBoxesIn: Seq[ErgoBox], - dataBoxesIn: Seq[ErgoBox], - rnd: RandomLike): (Seq[ErgoTransaction], Seq[ErgoBox]) = { - var createdEmissionBox: Seq[ErgoBox] = Seq() - - @tailrec - def loop(remainingCost: Long, - stateBoxes: Seq[ErgoBox], - selfBoxes: Seq[ErgoBox], - acc: Seq[ErgoTransaction], - rnd: RandomLike): (Seq[ErgoTransaction], Seq[ErgoBox]) = { - - lazy val dataBoxesToUse: IndexedSeq[ErgoBox] = { - Random.shuffle(dataBoxesIn ++ stateBoxesIn ++ selfBoxes).take(rnd.nextInt(10)).toIndexedSeq - } - - val currentSize = acc.map(_.size).sum - val averageSize = if (currentSize > 0) currentSize / acc.length else 1000 - val customTokens = (stateBoxes ++ selfBoxes).flatMap(_.additionalTokens.toArray) - val customTokensNum = customTokens.map(ct => ByteArrayWrapper(ct._1.toArray)).toSet.size - val issueNew = customTokensNum == 0 - - stateBoxes.find(isEmissionBox) match { - case Some(emissionBox) if currentSize < sizeLimit - averageSize => - // Extract money to anyoneCanSpend output and put emission to separate var to avoid it's double usage inside one block - val currentHeight: Int = emissionBox.creationHeight.toInt - val rewards = CandidateGenerator.collectRewards(Some(emissionBox), currentHeight, Seq.empty, defaultMinerPk, emptyStateContext) - val outs = rewards.flatMap(_.outputs) - val remainedBoxes = stateBoxes.filter(b => !isEmissionBox(b)) - createdEmissionBox = outs.filter(b => isEmissionBox(b)) - val newSelfBoxes = selfBoxes ++ outs.filter(b => !isEmissionBox(b)) - val cost: Long = getTxCost(rewards.head, Seq(emissionBox), Seq()) - loop(remainingCost - cost, remainedBoxes, newSelfBoxes, rewards ++ acc, rnd) - - case _ => - if (currentSize < sizeLimit - 2 * averageSize && remainingCost > 100000) { - val (consumedSelfBoxes, remainedSelfBoxes) = selfBoxes.splitAt(rnd.nextInt(2) + 1) - val (consumedBoxesFromState, remainedBoxes) = stateBoxes.splitAt(rnd.nextInt(2) + 1) - // disable tokens generation to avoid situation with too many tokens - val boxesToSpend = (consumedSelfBoxes ++ consumedBoxesFromState).toIndexedSeq - val tx = validTransactionFromBoxes(boxesToSpend, rnd, issueNew, dataBoxes = dataBoxesToUse) - tx.statelessValidity() match { - case Failure(e) => - log.warn(s"Failed to generate valid transaction: ${LoggingUtil.getReasonMsg(e)}") - loop(remainingCost, stateBoxes, selfBoxes, acc, rnd) - case _ => - val cost: Long = getTxCost(tx, boxesToSpend, dataBoxesToUse) - loop(remainingCost - cost, remainedBoxes, remainedSelfBoxes ++ tx.outputs, tx +: acc, rnd) - } - } else { - // take 2 remaining box from state and return transactions set - val (consumedSelfBoxes, remainedSelfBoxes) = selfBoxes.splitAt(1) - val boxesToSpend = if(stateBoxes.nonEmpty) stateBoxes.take(2) else consumedSelfBoxes - - val tx = validTransactionFromBoxes(boxesToSpend.toIndexedSeq, rnd, issueNew, dataBoxes = dataBoxesToUse) - val cost: Long = getTxCost(tx, boxesToSpend, dataBoxesToUse) - tx.statelessValidity() match { - case Success(_) if cost <= remainingCost => - ((tx +: acc).reverse, remainedSelfBoxes ++ tx.outputs ++ createdEmissionBox) - case Failure(e) => - log.warn(s"Failed to generate valid transaction: ${LoggingUtil.getReasonMsg(e)}") - loop(remainingCost, stateBoxes, selfBoxes, acc, rnd) - } - } - } - } - - loop(emptyStateContext.currentParameters.maxBlockCost, stateBoxesIn, mutable.WrappedArray.empty, mutable.WrappedArray.empty, rnd) - } - - protected def getTxCost(tx: ErgoTransaction, boxesToSpend: Seq[ErgoBox], dataBoxesToUse: Seq[ErgoBox]): Int = { - tx.statefulValidity( - tx.inputs.flatMap(i => boxesToSpend.find(_.id == i.boxId)), - tx.dataInputs.flatMap(i => dataBoxesToUse.find(_.id == i.boxId)), - emptyStateContext, - -2000000)(emptyVerifier).getOrElse(0) - } - - /** - * Simplified check that box is an emission box - */ - private def isEmissionBox(box: ErgoBox): Boolean = box.proposition == genesisEmissionBox.proposition - - /** @param txSizeLimit maximum transactions size in bytes */ - def validTransactionsFromBoxHolder(boxHolder: BoxHolder, - rnd: RandomLike, - txSizeLimit: Int = 10 * 1024): (Seq[ErgoTransaction], BoxHolder) = { - val (emissionBox, boxHolderWithoutEmission) = boxHolder.take(b => isEmissionBox(b)) - val (_, bhWithoutGenesis) = boxHolderWithoutEmission.take(b => genesisBoxes.contains(b)) - val (regularBoxes, drainedBh) = bhWithoutGenesis.take(rnd.nextInt(txSizeLimit / 100) + 1) - val boxes = emissionBox ++ regularBoxes - val dataBoxes: Seq[ErgoBox] = Random.shuffle(boxHolder.boxes.values).take(rnd.nextInt(txSizeLimit / 100)).toSeq - - assert(boxes.nonEmpty, s"Was unable to take at least 1 box from box holder $boxHolder") - val (txs, createdBoxes) = validTransactionsFromBoxes(txSizeLimit, boxes, dataBoxes, rnd) - txs.foreach(_.statelessValidity().get) - val bs = new BoxHolder(drainedBh.boxes ++ createdBoxes.map(b => ByteArrayWrapper(b.id) -> b)) - txs -> bs - } - - - def validTransactionsFromUtxoState(wus: WrappedUtxoState, rnd: RandomLike = new RandomWrapper): Seq[ErgoTransaction] = { - val num = 1 + rnd.nextInt(3) - - val allBoxes = wus.takeBoxes(num + rnd.nextInt(100)) - val anyoneCanSpendBoxes = allBoxes.filter(_.ergoTree == Constants.TrueLeaf) - val boxes = if (anyoneCanSpendBoxes.nonEmpty) anyoneCanSpendBoxes else allBoxes - - validTransactionsFromBoxes(num, boxes, rnd)._1 - } - - def validFullBlock(parentOpt: Option[ErgoFullBlock], utxoState: UtxoState, boxHolder: BoxHolder): ErgoFullBlock = - validFullBlock(parentOpt, utxoState, boxHolder, new RandomWrapper) - - - def validFullBlock(parentOpt: Option[ErgoFullBlock], utxoState: UtxoState, boxHolder: BoxHolder, rnd: RandomLike): ErgoFullBlock = { - validFullBlock(parentOpt, utxoState, validTransactionsFromBoxHolder(boxHolder, rnd)._1) - } - - def validFullBlockWithBoxHolder(parentOpt: Option[ErgoFullBlock], - utxoState: UtxoState, - boxHolder: BoxHolder, - rnd: RandomLike): (ErgoFullBlock, BoxHolder) = { - val txsBh = validTransactionsFromBoxHolder(boxHolder, rnd) - validFullBlock(parentOpt, utxoState, txsBh._1) -> txsBh._2 - } - - def validFullBlock(parentOpt: Option[ErgoFullBlock], - wrappedState: WrappedUtxoState): ErgoFullBlock = { - validFullBlock(parentOpt, wrappedState, wrappedState.versionedBoxHolder) - } - - def validFullBlock(parentOpt: Option[ErgoFullBlock], - wrappedState: WrappedUtxoState, - time: Long): ErgoFullBlock = { - validFullBlock( - parentOpt, - wrappedState, - validTransactionsFromBoxHolder(wrappedState.versionedBoxHolder, new RandomWrapper)._1, - Some(time) - ) - } - - def validFullBlock(parentOpt: Option[ErgoFullBlock], - utxoState: UtxoState, - transactions: Seq[ErgoTransaction], - timeOpt: Option[Long] = None): ErgoFullBlock = { - checkPayload(transactions, utxoState) - - val (adProofBytes, updStateDigest) = utxoState.proofsForTransactions(transactions).get - - val time = timeOpt.orElse(parentOpt.map(_.header.timestamp + 1)).getOrElse(System.currentTimeMillis()) - val interlinks = parentOpt.toSeq.flatMap { block => - nipopowAlgos.updateInterlinks(block.header, NipopowAlgos.unpackInterlinks(block.extension.fields).get) - } - val extension: ExtensionCandidate = - parameters.toExtensionCandidate ++ - nipopowAlgos.interlinksToExtension(interlinks) ++ - utxoState.stateContext.validationSettings.toExtensionCandidate - val votes = Array.fill(3)(0: Byte) - - powScheme.proveBlock(parentOpt.map(_.header), Header.InitialVersion, settings.chainSettings.initialNBits, updStateDigest, adProofBytes, - transactions, time, extension, votes, defaultMinerSecretNumber).get - } - - /** - * Full block valid against state only - allows to create blocks form headers and state, - * does not contain valid interlinks. - */ - def statefulyValidFullBlock(wrappedState: WrappedUtxoState, - timeOpt: Option[Long] = None): ErgoFullBlock = { - val parentOpt: Option[Header] = wrappedState.stateContext.lastHeaderOpt - val parentExtensionOpt: Option[Extension] = wrappedState.stateContext.lastExtensionOpt - val bh = wrappedState.versionedBoxHolder - val transactions = validTransactionsFromBoxHolder(bh, new RandomWrapper)._1 - - checkPayload(transactions, wrappedState) - - val (adProofBytes, updStateDigest) = wrappedState.proofsForTransactions(transactions).get - - val time = timeOpt.orElse(parentOpt.map(_.timestamp + 1)).getOrElse(System.currentTimeMillis()) - val interlinksExtension = nipopowAlgos.interlinksToExtension(nipopowAlgos.updateInterlinks(parentOpt, parentExtensionOpt)) - val extension: ExtensionCandidate = parameters.toExtensionCandidate ++ interlinksExtension - val votes = Array.fill(3)(0: Byte) - - powScheme.proveBlock(parentOpt, Header.InitialVersion, settings.chainSettings.initialNBits, updStateDigest, - adProofBytes, transactions, time, extension, votes, defaultMinerSecretNumber).get - } - - private def checkPayload(transactions: Seq[ErgoTransaction], us: UtxoState): Unit = { - transactions.foreach(_.statelessValidity() shouldBe 'success) - transactions.nonEmpty shouldBe true - ErgoState.boxChanges(transactions).get._1.foreach { case Remove(boxId) => - assert(us.boxById(boxId).isDefined, s"Box ${Algos.encode(boxId)} missed") - } - } - -} diff --git a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala b/ergo-core/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala deleted file mode 100644 index 5ec1522c19..0000000000 --- a/ergo-core/src/test/scala/org/ergoplatform/utils/generators/WalletGenerators.scala +++ /dev/null @@ -1,159 +0,0 @@ -package org.ergoplatform.utils.generators - -import org.ergoplatform._ -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.wallet.IdUtils._ -import org.ergoplatform.nodeView.wallet.persistence.WalletDigest -import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequest, BurnTokensRequest, PaymentRequest} -import org.ergoplatform.nodeView.wallet.scanning._ -import org.ergoplatform.settings.Constants -import org.ergoplatform.wallet.Constants.ScanId -import org.ergoplatform.wallet.boxes.TrackedBox -import org.ergoplatform.wallet.utils.Generators -import org.scalacheck.Gen -import sigmastate.Values.ByteArrayConstant - -trait WalletGenerators extends ErgoTransactionGenerators with Generators { - - override def trackedBoxGen: Gen[TrackedBox] = { - Gen.oneOf( - unspentOffchainBoxGen, - unspentOnchainBoxGen, - spentOffchainBoxGen, - spentPartiallyOffchainBoxGen, - spentOnchainBoxGen - ) - } - - def unspentOffchainBoxGen: Gen[TrackedBox] = { - for { - (boxes, tx) <- validErgoTransactionGen - outIndex <- outIndexGen(tx) - ergoBox <- Gen.oneOf(boxes) - appStatuses <- appStatusesGen - } yield TrackedBox(tx, outIndex, None, ergoBox, appStatuses) - } - - def unspentOnchainBoxGen: Gen[TrackedBox] = { - for { - (boxes, tx) <- validErgoTransactionGen - outIndex <- outIndexGen(tx) - height <- heightGen() - ergoBox <- Gen.oneOf(boxes) - appStatuses <- appStatusesGen - } yield TrackedBox(tx, outIndex, Some(height), ergoBox, appStatuses) - } - - def spentOffchainBoxGen: Gen[TrackedBox] = { - for { - (boxes, tx) <- validErgoTransactionGen - (_, spendingTx) <- validErgoTransactionGen - outIndex <- outIndexGen(tx) - ergoBox <- Gen.oneOf(boxes) - appStatuses <- appStatusesGen - } yield TrackedBox(tx.id, outIndex, None, Some(spendingTx.id), None, ergoBox, appStatuses) - } - - def spentPartiallyOffchainBoxGen: Gen[TrackedBox] = { - for { - (boxes, tx) <- validErgoTransactionGen - (_, spendingTx) <- validErgoTransactionGen - outIndex <- outIndexGen(tx) - height <- heightGen() - ergoBox <- Gen.oneOf(boxes) - appStatuses <- appStatusesGen - } yield TrackedBox(tx.id, outIndex, Some(height), Some(spendingTx.id), None, ergoBox, appStatuses) - } - - def spentOnchainBoxGen: Gen[TrackedBox] = { - for { - (boxes, tx) <- validErgoTransactionGen - (_, spendingTx) <- validErgoTransactionGen - outIndex <- outIndexGen(tx) - height <- heightGen() - spendingHeight <- heightGen(height) - ergoBox <- Gen.oneOf(boxes) - appStatuses <- appStatusesGen - } yield TrackedBox( - tx.id, outIndex, Some(height), Some(spendingTx.id), Some(spendingHeight), ergoBox, appStatuses) - } - - def paymentRequestGen: Gen[PaymentRequest] = { - for { - value <- Gen.choose(1L, 100000L) - assets <- additionalTokensGen - registers <- additionalRegistersGen - } yield PaymentRequest(Pay2SAddress(Constants.FalseLeaf), value, assets, registers) - } - - def burnTokensRequestGen: Gen[BurnTokensRequest] = { - for { - assets <- additionalTokensGen - } yield BurnTokensRequest(assets) - } - - def assetIssueRequestGen: Gen[AssetIssueRequest] = { - for { - amount <- Gen.choose(1L, 100000L) - name <- Gen.alphaUpperStr - description <- Gen.alphaLowerStr - decimals <- Gen.choose(4, 16) - } yield AssetIssueRequest(Pay2SAddress(Constants.FalseLeaf), None, amount, name, description, decimals) - } - - def registrySummaryGen: Gen[WalletDigest] = { - for { - height <- Gen.posNum[Int] - amount <- Gen.choose(1L, 100000L) - balances <- additionalTokensGen - } yield { - val encodedBalances = balances.map { case (x1, x2) => encodedTokenId(x1) -> x2 } - WalletDigest(height, amount, encodedBalances) - } - } - - def registerIdGen: Gen[ErgoBox.RegisterId] = Gen.oneOf(ErgoBox.allRegisters) - - def containsScanningPredicateGen: Gen[ContainsScanningPredicate] = for { - regId <- registerIdGen - bs <- nonEmptyBytesGen - } yield ContainsScanningPredicate(regId, ByteArrayConstant(bs)) - - def equalsScanningPredicateGen: Gen[EqualsScanningPredicate] = for { - regId <- registerIdGen - bs <- nonEmptyBytesGen - } yield EqualsScanningPredicate(regId, ByteArrayConstant(bs)) - - def containsAssetPredicateGen: Gen[ContainsAssetPredicate] = for { - asset <- assetGen - } yield ContainsAssetPredicate(asset._1) - - def orScanningPredicateGen: Gen[OrScanningPredicate] = for { - args <- Gen.nonEmptyListOf(Gen.oneOf(containsScanningPredicateGen, equalsScanningPredicateGen, - containsAssetPredicateGen)) - } yield OrScanningPredicate(args: _*) - - def andScanningPredicateGen: Gen[AndScanningPredicate] = for { - args <- Gen.nonEmptyListOf(Gen.oneOf(containsScanningPredicateGen, equalsScanningPredicateGen, - containsAssetPredicateGen, orScanningPredicateGen)) - } yield AndScanningPredicate(args: _*) - - def scanningPredicateGen: Gen[ScanningPredicate] = for { - predicate <- Gen.oneOf(andScanningPredicateGen, orScanningPredicateGen) - } yield predicate - - def externalScanReqGen: Gen[ScanRequest] = for { - appName <- Gen.alphaNumStr - pred <- scanningPredicateGen - } yield ScanRequest(appName, pred, Some(ScanWalletInteraction.Off), Some(true)) - - def externalAppGen: Gen[Scan] = for { - scanId <- Gen.posNum[Short] - req <- externalScanReqGen - } yield req.toScan(ScanId @@ scanId).get - - private def outIndexGen(tx: ErgoTransaction) = Gen.choose(0: Short, tx.outputCandidates.length.toShort) - - private def heightGen(min: Int = 0) = Gen.choose(min + 1, Integer.MAX_VALUE / 2 + min) - -} diff --git a/ergo-core/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala b/ergo-core/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala deleted file mode 100644 index 4c7e5ad532..0000000000 --- a/ergo-core/src/test/scala/scorex/core/network/DeliveryTrackerSpec.scala +++ /dev/null @@ -1,71 +0,0 @@ -package scorex.core.network - -import akka.actor.{ActorRef, Cancellable} -import io.circe._ -import io.circe.syntax._ -import org.ergoplatform.modifiers.NetworkObjectTypeId -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.core.network.ModifiersStatus.Received -import scorex.testkit.generators.ObjectGenerators -import scorex.util.ModifierId - -class DeliveryTrackerSpec extends ErgoPropertyTest with ObjectGenerators { - - property("tracker should accept requested modifiers, turn them into received and clear them") { - forAll(connectedPeerGen(ActorRef.noSender)) { peer => - val tracker = DeliveryTracker.empty(settings) - val mid: ModifierId = ModifierId @@ "foo" - val mTypeId: NetworkObjectTypeId.Value = NetworkObjectTypeId.fromByte(104) - tracker.setRequested(mTypeId, mid, peer) { _ => Cancellable.alreadyCancelled} - val infoFields = - Seq( - "address" -> peer.connectionId.remoteAddress.toString.asJson, - "checks" -> 0.asJson - ) ++ peer.peerInfo.map(_.peerSpec.protocolVersion.toString.asJson).map("version" -> _) - tracker.fullInfo.asJson shouldBe Json.obj( - "invalidModifierApproxSize" -> 0.asJson, - "requested" -> Json.obj( - "104" -> Json.obj( - "foo" -> Json.obj(infoFields:_*) - ) - ), - "received" -> Json.obj() - ) - - tracker.setReceived(mid, mTypeId, peer) - val infoFields2 = - Seq( - "address" -> peer.connectionId.remoteAddress.toString.asJson - ) ++ peer.peerInfo.map(_.peerSpec.protocolVersion.toString.asJson).map("version" -> _) - - tracker.fullInfo.asJson shouldBe Json.obj( - "invalidModifierApproxSize" -> 0.asJson, - "requested" -> Json.obj( - "104" -> Json.obj(), - ), - "received" -> Json.obj( - "104" -> Json.obj( - "foo" -> Json.obj(infoFields2:_*) - ), - ) - ) - tracker.clearStatusForModifier(mid, mTypeId, Received) - tracker.fullInfo.asJson shouldBe Json.obj( - "invalidModifierApproxSize" -> 0.asJson, - "requested" -> Json.obj( - "104" -> Json.obj(), - ), - "received" -> Json.obj( - "104" -> Json.obj() - ) - ) - - tracker.reset() - val fullInfoAfterReset = tracker.fullInfo - fullInfoAfterReset.invalidModifierApproxSize shouldBe 0 - fullInfoAfterReset.requested.size shouldBe 0 - fullInfoAfterReset.received.size shouldBe 0 - } - } - -} diff --git a/ergo-core/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala b/ergo-core/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala deleted file mode 100644 index 13b8c3d0be..0000000000 --- a/ergo-core/src/test/scala/scorex/core/network/PeerSpecSerializerSpec.scala +++ /dev/null @@ -1,21 +0,0 @@ -package scorex.core.network - -import org.ergoplatform.utils.ErgoPropertyTest -import scorex.testkit.generators.ObjectGenerators -import scorex.util.ByteArrayBuilder -import scorex.util.serialization.{VLQByteBufferReader, VLQByteBufferWriter} - -import java.nio.ByteBuffer - -class PeerSpecSerializerSpec extends ErgoPropertyTest with ObjectGenerators { - - property("All variants of peer spec should be serialized and deserialized successfully") { - forAll(peerSpecGen) { peerSpec => - val writer = new VLQByteBufferWriter(new ByteArrayBuilder()) - PeerSpecSerializer.serialize(peerSpec, writer) - val reader = new VLQByteBufferReader(ByteBuffer.wrap(writer.result().toBytes)) - val actualPeerSpec = PeerSpecSerializer.parse(reader) - peerSpec shouldBe actualPeerSpec - } - } -} diff --git a/ergo-core/src/test/scala/scorex/testkit/SerializationTests.scala b/ergo-core/src/test/scala/scorex/testkit/SerializationTests.scala deleted file mode 100644 index b4ed96389e..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/SerializationTests.scala +++ /dev/null @@ -1,16 +0,0 @@ -package scorex.testkit - -import org.scalacheck.Gen -import org.scalatest.Assertion -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.core.serialization.ErgoSerializer - -trait SerializationTests extends ScalaCheckPropertyChecks with Matchers { - def checkSerializationRoundtrip[A](generator: Gen[A], serializer: ErgoSerializer[A]): Assertion = { - forAll(generator) { b: A => - val recovered = serializer.parseBytes(serializer.toBytes(b)) - serializer.toBytes(b) shouldEqual serializer.toBytes(recovered) - } - } -} diff --git a/ergo-core/src/test/scala/scorex/testkit/TestkitHelpers.scala b/ergo-core/src/test/scala/scorex/testkit/TestkitHelpers.scala deleted file mode 100644 index a6d1654a63..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/TestkitHelpers.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scorex.testkit - -trait TestkitHelpers { - - val MinTestsOk = 100 - - def check(minTestsOk:Int)(f: Int => Unit): Unit = (0 until minTestsOk) foreach (i => f(i)) - - def check(f: Int => Unit): Unit = check(MinTestsOk)(f) -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala b/ergo-core/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala deleted file mode 100644 index 857fd49393..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/AllModifierProducers.scala +++ /dev/null @@ -1,11 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.nodeView.state.ErgoState - - -trait AllModifierProducers[ST <: ErgoState[ST]] - extends SemanticallyValidModifierProducer[ST] - with SyntacticallyTargetedModifierProducer - with ArbitraryTransactionsCarryingModifierProducer - with TotallyValidModifierProducer[ST] - with SemanticallyValidTransactionsCarryingModifier[ST] diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala deleted file mode 100644 index 4bbed68c85..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/ArbitraryTransactionsCarryingModifierProducer.scala +++ /dev/null @@ -1,12 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.mempool.ErgoMemPool -/** - * Produces a modifier with transactions, not necessary syntatically or semantically valid - */ -trait ArbitraryTransactionsCarryingModifierProducer{ - -def modifierWithTransactions(memoryPoolOpt: Option[ErgoMemPool], customTransactionsOpt: Option[Seq[ErgoTransaction]]): BlockTransactions -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/CoreGenerators.scala b/ergo-core/src/test/scala/scorex/testkit/generators/CoreGenerators.scala deleted file mode 100644 index 54c6c3d752..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/CoreGenerators.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scorex.testkit.generators - -import org.scalacheck.Gen -import scorex.core.{VersionTag, idToVersion} - -//Generators of objects from scorex-core -trait CoreGenerators extends ObjectGenerators { - lazy val versionTagGen: Gen[VersionTag] = modifierIdGen.map(id => idToVersion(id)) -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/CustomModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/CustomModifierProducer.scala deleted file mode 100644 index 42d4278fe2..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/CustomModifierProducer.scala +++ /dev/null @@ -1,17 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.ErgoState - -sealed trait ModifierProducerTemplateItem - -case object SynInvalid extends ModifierProducerTemplateItem -case object Valid extends ModifierProducerTemplateItem - -trait CustomModifierProducer[ST <: ErgoState[ST]] { - - def customModifiers(history: ErgoHistory, - state: ST, - template: Seq[ModifierProducerTemplateItem]): Seq[BlockSection] -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala b/ergo-core/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala deleted file mode 100644 index f99112fab7..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/ObjectGenerators.scala +++ /dev/null @@ -1,115 +0,0 @@ -package scorex.testkit.generators - -import java.net.{InetAddress, InetSocketAddress, URL} -import akka.actor.ActorRef -import akka.util.ByteString -import org.ergoplatform.modifiers.NetworkObjectTypeId -import org.ergoplatform.network.ModePeerFeature -import org.ergoplatform.nodeView.state.StateType -import org.scalacheck.Gen.{const, some} -import org.scalacheck.{Arbitrary, Gen} -import scorex.core.app.Version -import scorex.core.network.message.{InvData, ModifiersData} -import scorex.core.network._ -import scorex.core.network.peer.{PeerInfo, RestApiUrlPeerFeature} -import scorex.core.NodeViewModifier -import scorex.util.{ModifierId, bytesToId} - -trait ObjectGenerators { - - val MaxVersion = 999 - val MaxIp = 255 - val MaxPort = 65535 - - val modePeerFeatureGen = for { - utxo <- Gen.oneOf(true, false) - stateType <- if(utxo) StateType.Utxo else StateType.Digest - verifyingTransactions <- Gen.oneOf(true, false) - popowSuffix <- Gen.option(smallInt) - blocksToKeep <- smallInt - } yield ModePeerFeature(stateType, verifyingTransactions, popowSuffix, blocksToKeep) - - lazy val smallInt: Gen[Int] = Gen.choose(0, 20) - - lazy val nonEmptyBytesGen: Gen[Array[Byte]] = Gen.nonEmptyListOf(Arbitrary.arbitrary[Byte]) - .map(_.toArray).suchThat(_.length > 0) - - lazy val nonEmptyByteStringGen: Gen[ByteString] = nonEmptyBytesGen.map(ByteString(_)) - - def genBoundedBytes(minSize: Int, maxSize: Int): Gen[Array[Byte]] = { - Gen.choose(minSize, maxSize) flatMap { sz => Gen.listOfN(sz, Arbitrary.arbitrary[Byte]).map(_.toArray) } - } - - def genBytes(size: Int): Gen[Array[Byte]] = genBoundedBytes(size, size) - - lazy val positiveLongGen: Gen[Long] = Gen.choose(1, Long.MaxValue) - - lazy val positiveByteGen: Gen[Byte] = Gen.choose(1, Byte.MaxValue) - - - lazy val modifierIdGen: Gen[ModifierId] = Gen.listOfN(NodeViewModifier.ModifierIdSize, Arbitrary.arbitrary[Byte]) - .map(id => bytesToId(id.toArray)) - - lazy val modifierTypeIdGen: Gen[NetworkObjectTypeId.Value] = Arbitrary.arbitrary[Byte].map(t => NetworkObjectTypeId.fromByte(t)) - - lazy val invDataGen: Gen[InvData] = for { - modifierTypeId: NetworkObjectTypeId.Value <- modifierTypeIdGen - modifierIds: Seq[ModifierId] <- Gen.nonEmptyListOf(modifierIdGen) if modifierIds.nonEmpty - } yield InvData(modifierTypeId, modifierIds) - - lazy val modifierWithIdGen: Gen[(ModifierId, Array[Byte])] = for { - id <- modifierIdGen - mod <- nonEmptyBytesGen - } yield id -> mod - - lazy val modifiersGen: Gen[ModifiersData] = for { - modifierTypeId: NetworkObjectTypeId.Value <- modifierTypeIdGen - modifiers: Map[ModifierId, Array[Byte]] <- Gen.nonEmptyMap(modifierWithIdGen).suchThat(_.nonEmpty) - } yield ModifiersData(modifierTypeId, modifiers) - - lazy val appVersionGen: Gen[Version] = for { - fd <- Gen.choose(0: Byte, Byte.MaxValue) - sd <- Gen.choose(0: Byte, Byte.MaxValue) - td <- Gen.choose(0: Byte, Byte.MaxValue) - } yield Version(fd, sd, td) - - lazy val inetSocketAddressGen: Gen[InetSocketAddress] = for { - ip1 <- Gen.choose(0, MaxIp) - ip2 <- Gen.choose(0, MaxIp) - ip3 <- Gen.choose(0, MaxIp) - ip4 <- Gen.choose(0, MaxIp) - port <- Gen.choose(0, MaxPort) - } yield new InetSocketAddress(InetAddress.getByName(s"$ip1.$ip2.$ip3.$ip4"), port) - - lazy val urlGen: Gen[URL] = for { - protocol <- Gen.frequency(5 -> const("http://"), 5 -> const("https://")) - ip1 <- Gen.choose(0, MaxIp) - ip2 <- Gen.choose(0, MaxIp) - ip3 <- Gen.choose(0, MaxIp) - ip4 <- Gen.choose(0, MaxIp) - host <- Gen.frequency(5 -> const(s"$ip1.$ip2.$ip3.$ip4"), 5 -> const("example.com")) - port <- Gen.choose(0, MaxPort) - suffix <- Gen.frequency(5 -> const("/"), 5 -> const("")) - } yield new URL(s"$protocol$host:$port$suffix") - - lazy val connectionIdGen: Gen[ConnectionId] = for { - ip1 <- inetSocketAddressGen - ip2 <- inetSocketAddressGen - direction <- Gen.oneOf[ConnectionDirection](Seq[ConnectionDirection](Incoming, Outgoing)) - } yield ConnectionId(ip1, ip2, direction) - - def peerInfoGen: Gen[PeerInfo] = for { - peerSpec <- peerSpecGen - } yield PeerInfo(peerSpec, 0L, Some(Incoming), 0L) - - def connectedPeerGen(peerRef: ActorRef): Gen[ConnectedPeer] = for { - connectionId <- connectionIdGen - peerInfo <- peerInfoGen - } yield ConnectedPeer(connectionId, peerRef, Some(peerInfo)) - - def peerSpecGen: Gen[PeerSpec] = for { - declaredAddress <- Gen.frequency(5 -> const(None), 5 -> some(inetSocketAddressGen)) - features: Seq[PeerFeature] <- Gen.someOf(modePeerFeatureGen, urlGen.flatMap(url => RestApiUrlPeerFeature(url))) - version <- appVersionGen - } yield PeerSpec("ergoref", version, "ergo-node", declaredAddress, features) -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyInvalidModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyInvalidModifierProducer.scala deleted file mode 100644 index 015456a936..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyInvalidModifierProducer.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.state.ErgoState - - -trait SemanticallyInvalidModifierProducer[ST <: ErgoState[ST]] { - def semanticallyInvalidModifier(state: ST): BlockSection -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidModifierProducer.scala deleted file mode 100644 index 33a4e9188b..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidModifierProducer.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.state.ErgoState - -trait SemanticallyValidModifierProducer[ST <: ErgoState[ST]] { - def semanticallyValidModifier(state: ST): BlockSection -} - - diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala b/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala deleted file mode 100644 index bc43d23eea..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/SemanticallyValidTransactionsCarryingModifier.scala +++ /dev/null @@ -1,12 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.history.BlockTransactions -import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.state.ErgoState - -trait SemanticallyValidTransactionsCarryingModifier[ST <: ErgoState[ST]] { - - def semanticallyValidModifier(state: ST): BlockTransactions - def genValidTransactionPair(state: ST): Seq[ErgoTransaction] - def semanticallyValidModifierWithCustomTransactions(state: ST, transactions: Seq[ErgoTransaction]): BlockTransactions -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/SyntacticallyTargetedModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/SyntacticallyTargetedModifierProducer.scala deleted file mode 100644 index c7964259e9..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/SyntacticallyTargetedModifierProducer.scala +++ /dev/null @@ -1,11 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.history.ErgoHistory - - -trait SyntacticallyTargetedModifierProducer { - def syntacticallyValidModifier(history: ErgoHistory): BlockSection - - def syntacticallyInvalidModifier(history: ErgoHistory): BlockSection -} diff --git a/ergo-core/src/test/scala/scorex/testkit/generators/TotallyValidModifierProducer.scala b/ergo-core/src/test/scala/scorex/testkit/generators/TotallyValidModifierProducer.scala deleted file mode 100644 index 4373af4332..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/generators/TotallyValidModifierProducer.scala +++ /dev/null @@ -1,13 +0,0 @@ -package scorex.testkit.generators - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.state.ErgoState - - -trait TotallyValidModifierProducer[ST <: ErgoState[ST]] { - - def totallyValidModifier(history: ErgoHistory, state: ST): BlockSection - - def totallyValidModifiers(history: ErgoHistory, state: ST, count: Int): Seq[BlockSection] -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/HistoryTests.scala b/ergo-core/src/test/scala/scorex/testkit/properties/HistoryTests.scala deleted file mode 100644 index 31e2d726e8..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/HistoryTests.scala +++ /dev/null @@ -1,86 +0,0 @@ -package scorex.testkit.properties - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.history.ErgoHistory -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.core.consensus.ModifierSemanticValidity.Valid -import scorex.testkit.TestkitHelpers -import scorex.testkit.generators.SyntacticallyTargetedModifierProducer -import scorex.util.ScorexLogging - - -trait HistoryTests - extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers - with ScorexLogging - with TestkitHelpers - with SyntacticallyTargetedModifierProducer { - - val historyGen: Gen[ErgoHistory] - - lazy val generatorWithValidModifier: Gen[(ErgoHistory, BlockSection)] = { - historyGen.map { h => (h, syntacticallyValidModifier(h))} - } - - lazy val generatorWithInvalidModifier: Gen[(ErgoHistory, BlockSection)] = { - historyGen.map { h => (h, syntacticallyInvalidModifier(h))} - } - - private def propertyNameGenerator(propName: String): String = s"HistoryTests: $propName" - - property(propertyNameGenerator("applicable with valid modifier")) { - forAll(generatorWithValidModifier) { case (h, m) => h.applicableTry(m) shouldBe 'success} - } - - property(propertyNameGenerator("append valid modifier")) { - forAll(generatorWithValidModifier) { case (h, m) => h.append(m).isSuccess shouldBe true } - } - - property(propertyNameGenerator("contain valid modifier after appending")) { - forAll(generatorWithValidModifier) { case (h, m) => - h.append(m) - h.contains(m) shouldBe true - } - } - - property(propertyNameGenerator("find valid modifier after appending by modifierId")) { - forAll(generatorWithValidModifier) { case (h, m) => - h.append(m) - h.modifierById(m.id) shouldBe defined - } - } - - property(propertyNameGenerator("report semantically validation after appending valid modifier")) { - forAll(generatorWithValidModifier) { case (h, m) => - h.append(m) - h.reportModifierIsValid(m).get - h.isSemanticallyValid(m.id) shouldBe Valid - } - } - - property(propertyNameGenerator("not applicable with invalid modifier")) { - forAll(generatorWithInvalidModifier) { case (h, m) => h.applicableTry(m) shouldBe 'failure} - } - - property(propertyNameGenerator("not append invalid modifier")) { - forAll(generatorWithInvalidModifier) { case (h, m) => h.append(m).isSuccess shouldBe false } - } - - property(propertyNameGenerator("not contain invalid modifier after appending")) { - forAll(generatorWithInvalidModifier) { case (h, m) => - h.append(m) - h.contains(m) shouldBe false - } - } - - property(propertyNameGenerator("not finds valid modifier after appending by modifierId")) { - forAll(generatorWithInvalidModifier) { case (h, m) => - h.append(m) - h.modifierById(m.id) shouldBe None - } - } -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala b/ergo-core/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala deleted file mode 100644 index 775b58d8d0..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala +++ /dev/null @@ -1,337 +0,0 @@ -package scorex.testkit.properties - -import akka.actor._ -import akka.testkit.TestProbe -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.history.ErgoHistory -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ -import org.ergoplatform.nodeView.state.ErgoState -import scorex.testkit.generators._ -import scorex.testkit.utils.AkkaFixture -import scorex.util.ScorexLogging - -import scala.concurrent.Await -import scala.concurrent.duration._ - -@SuppressWarnings(Array("org.wartremover.warts.TraversableOps")) -trait NodeViewHolderTests[ST <: ErgoState[ST]] - extends AnyPropSpec - with Matchers - with ScorexLogging - with SyntacticallyTargetedModifierProducer - with TotallyValidModifierProducer[ST] - with SemanticallyInvalidModifierProducer[ST] - with CustomModifierProducer[ST] - with ObjectGenerators { - - def nodeViewHolder(implicit system: ActorSystem): (ActorRef, TestProbe, BlockSection, ST, ErgoHistory) - - class HolderFixture extends AkkaFixture { - @SuppressWarnings(Array("org.wartremover.warts.PublicInference")) - val (node, eventListener, mod, s, h) = nodeViewHolder - } - - private def withFixture(testCode: HolderFixture => Any): Unit = { - val fixture = new HolderFixture - try { - testCode(fixture) - } finally { - Await.result(fixture.system.terminate(), Duration.Inf) - } - } - - private type CurrentViewType = CurrentView[ST] - - private def withView[T](node: ActorRef)(f: CurrentViewType => T) - (implicit system: ActorSystem): T = { - val probe = TestProbe() - probe.send(node, - GetDataFromCurrentView[ST, CurrentViewType] { view => view }) - val view = probe.expectMsgClass(10.seconds, classOf[CurrentViewType]) - f(view) - } -/* todo: fix - property("NodeViewHolder: modifiers from remote") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[ModifiersRemovedFromCache]) - p.send(node, ModifiersFromRemote(Seq(mod))) - eventListener.expectMsgType[ModifiersRemovedFromCache] - } - }*/ - - property("NodeViewHolder syntactically valid modifier subscription") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head }) - val mod = p.expectMsgClass(classOf[BlockSection]) - p.send(node, LocallyGeneratedModifier(mod)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - } - } - - property("NodeViewHolder: syntactically failed modifier subscription") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification]) - val invalid = syntacticallyInvalidModifier(h) - p.send(node, LocallyGeneratedModifier(invalid)) - eventListener.expectMsgType[SyntacticallyFailedModification] - } - } - - property("NodeViewHolder: semantically valid modifier subscription") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[FullBlockApplied]) - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head }) - val mod = p.expectMsgClass(classOf[BlockSection]) - p.send(node, LocallyGeneratedModifier(mod)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - eventListener.expectMsgType[FullBlockApplied] - } - } - - property("NodeViewHolder: semantically failed modifier subscription") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[SemanticallyFailedModification]) - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => semanticallyInvalidModifier(v.state) }) - val invalid = p.expectMsgClass(classOf[BlockSection]) - p.send(node, LocallyGeneratedModifier(invalid)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - eventListener.expectMsgType[SemanticallyFailedModification] - } - } - - property("NodeViewHolder: syntactically/semantically valid modifier subscription") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[FullBlockApplied]) - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => totallyValidModifiers(v.history, v.state, 2).head }) - val mod = p.expectMsgClass(classOf[BlockSection]) - p.send(node, LocallyGeneratedModifier(mod)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - eventListener.expectMsgType[FullBlockApplied] - } - } - - property("NodeViewHolder: check state after creation") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - p.send(node, GetDataFromCurrentView[ST, Boolean] { v => - v.state.version == s.version - }) - p.expectMsg(true) - } - } - - property("NodeViewHolder: check that a valid modifier is applicable") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - p.send(node, GetDataFromCurrentView[ST, Boolean] { v => - v.history.applicableTry(mod).isSuccess - }) - p.expectMsg(true) - } - } - - property("NodeViewHolder: check that valid modifiers are applicable") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification]) - p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => - totallyValidModifiers(v.history, v.state, 10) //todo: fix magic number - }) - val mods = p.expectMsgClass(classOf[Seq[BlockSection]]) - - mods.foreach { mod => - p.send(node, LocallyGeneratedModifier(mod)) - } - - (1 to mods.size).foreach(_ => eventListener.expectMsgType[SyntacticallySuccessfulModifier]) - } - } - - property("NodeViewHolder: apply locally generated mod") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification]) - - val invalid = syntacticallyInvalidModifier(h) - - p.send(node, LocallyGeneratedModifier(invalid)) - - eventListener.expectMsgType[SyntacticallyFailedModification] - - p.send(node, LocallyGeneratedModifier(mod)) - - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - - p.send(node, GetDataFromCurrentView[ST, Boolean] { v => - v.state.version == s.version && v.history.contains(mod.id) - }) - - p.expectMsg(true) - } - } - - property("NodeViewHolder: simple forking") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - val waitDuration = 5.seconds - - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallySuccessfulModifier]) - system.eventStream.subscribe(eventListener.ref, classOf[SyntacticallyFailedModification]) - - p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => totallyValidModifiers(v.history, v.state, 2) }) - val initMods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]]) - initMods.foreach { mod => - p.send(node, LocallyGeneratedModifier(mod)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - } - - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => - totallyValidModifiers(v.history, v.state, 2).head - }) - val fork1Mod = p.expectMsgClass(waitDuration, classOf[BlockSection]) - - p.send(node, GetDataFromCurrentView[ST, BlockSection] { v => - totallyValidModifiers(v.history, v.state, 2).head - }) - val fork2Mod = p.expectMsgClass(waitDuration, classOf[BlockSection]) - - p.send(node, LocallyGeneratedModifier(fork1Mod)) - p.send(node, LocallyGeneratedModifier(fork2Mod)) - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - eventListener.expectMsgType[SyntacticallySuccessfulModifier] - - p.send(node, GetDataFromCurrentView[ST, Boolean] { v => - v.history.contains(fork1Mod.id) || v.history.contains(fork2Mod.id) - }) - - p.expectMsg(10.seconds, true) - } - } - - /** - * In this test we apply first a chain of 2 blocks and then a chain of 4 blocks, both started with the same - * common block. We are expecting to observe "switching" here, though with non-chain structures there could be no - * notion of switching, so what we check finally is that last block from the second chain is in "open surface" - * (list of open blocks which do not have successors yet, size of the list is 1 in case of blockchain) - */ - property("NodeViewHolder: forking - switching") { - withFixture { ctx => - import ctx._ - val p = TestProbe() - - val opCountBeforeFork = 10 - val fork1OpCount = 2 - val fork2OpCount = 4 - - val waitDuration = 10.seconds - - //some base operations, we don't wanna have fork right from genesis - p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => - totallyValidModifiers(v.history, v.state, opCountBeforeFork) - }) - val plainMods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]]) - plainMods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) } - - p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => - val mods = totallyValidModifiers(v.history, v.state, fork1OpCount) - assert(mods.head.parentId == v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).get) - mods - }) - val fork1Mods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]]) - - p.send(node, GetDataFromCurrentView[ST, Seq[BlockSection]] { v => - totallyValidModifiers(v.history, v.state, fork2OpCount) - }) - val fork2Mods = p.expectMsgClass(waitDuration, classOf[Seq[BlockSection]]) - - fork1Mods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) } - fork2Mods.foreach { mod => p.send(node, LocallyGeneratedModifier(mod)) } - - p.send(node, GetDataFromCurrentView[ST, Boolean] { v => - v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).contains(fork2Mods.last.id) - }) - p.expectMsg(true) - } - } - - property("NodeViewHolder: forking - switching with an invalid block") { - withFixture { ctx => - import ctx._ - - val opCountBeforeFork = 10 - val fork1OpCount = 4 - - //some base operations, we don't wanna have fork right from genesis - withView(node) { v => - totallyValidModifiers(v.history, v.state, opCountBeforeFork) - }.foreach { - mod => node ! LocallyGeneratedModifier(mod) - } - // generate the first fork with valid blocks - val fork1Mods = withView(node) { v => - val mods = totallyValidModifiers(v.history, v.state, fork1OpCount) - assert(mods.head.parentId == v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).get) - mods - } - // generate the second fork with the invalid block - val fork2Mods = withView(node) { v => - customModifiers(v.history, v.state, - Seq[ModifierProducerTemplateItem](Valid, - SynInvalid, // invalid modifier - Valid, Valid, Valid, Valid, Valid, Valid)) - } - // apply the first fork with valid blocks - fork1Mods.foreach { mod => node ! LocallyGeneratedModifier(mod) } - // apply the second fork with invalid block - fork2Mods.foreach { mod => node ! LocallyGeneratedModifier(mod) } - // verify that open surface consist of last block of the first chain, - // or first block of the second chain, or both, but no any other option - withView(node) { v => - v.history.bestFullBlockIdOpt.orElse(v.history.bestHeaderIdOpt).toSeq should ( - contain only fork1Mods.last.id - or contain only fork2Mods.head.id - or contain only(fork1Mods.last.id, fork2Mods.head.id) - ) - } - } - } - -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MemoryPoolTest.scala b/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MemoryPoolTest.scala deleted file mode 100644 index 3ee1108614..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MemoryPoolTest.scala +++ /dev/null @@ -1,13 +0,0 @@ -package scorex.testkit.properties.mempool - -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.scalacheck.Gen - - -trait MemoryPoolTest { - val memPool: ErgoMemPool - val memPoolGenerator: Gen[ErgoMemPool] - val transactionGenerator: Gen[ErgoTransaction] - val unconfirmedTxGenerator: Gen[UnconfirmedTransaction] -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolFilterPerformanceTest.scala b/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolFilterPerformanceTest.scala deleted file mode 100644 index 0d482a790a..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolFilterPerformanceTest.scala +++ /dev/null @@ -1,43 +0,0 @@ -package scorex.testkit.properties.mempool - -import java.security.MessageDigest -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks - -trait MempoolFilterPerformanceTest - extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers - with MemoryPoolTest { - - var initializedMempool: Option[ErgoMemPool] = None - - val thresholdInHashes = 500000 - - private val HeatJVMHashesCount = 1000000 //to heat up JVM, just in case it is cold - - val thresholdSecs: Double = { - //heat up - (1 to HeatJVMHashesCount).foreach(i => MessageDigest.getInstance("SHA-256").digest(("dummy" + i).getBytes())) - - val t0 = System.currentTimeMillis() - (1 to thresholdInHashes).foreach(i => MessageDigest.getInstance("SHA-256").digest(("dummy" + i).getBytes())) - val t = System.currentTimeMillis() - (t - t0) / 1000.0 - } - - property("Mempool should be able to store a lot of transactions") { - var m: ErgoMemPool = memPool - (0 until 1000) foreach { _ => - forAll(transactionGenerator) { tx: ErgoTransaction => - m = m.put(UnconfirmedTransaction(tx, None)) - } - } - m.size should be > 1000 - initializedMempool = Some(m) - } - -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala b/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala deleted file mode 100644 index 5506e6ac35..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolRemovalTest.scala +++ /dev/null @@ -1,41 +0,0 @@ -package scorex.testkit.properties.mempool - -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.testkit.TestkitHelpers -import scorex.testkit.generators.ArbitraryTransactionsCarryingModifierProducer -import scorex.util.ScorexLogging - -trait MempoolRemovalTest extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers - with ScorexLogging - with TestkitHelpers - with MemoryPoolTest - with ArbitraryTransactionsCarryingModifierProducer { - - val historyGen: Gen[ErgoHistory] - - //todo: this test doesn't check anything. It should be reworked as a test for node view holder - property("Transactions once added to block should be removed from Mempool") { - val min = 1 - val max = 10 - forAll(Gen.choose(min, max)) { _ => - var m: ErgoMemPool = memPool - // var h: ErgoHistory = historyGen.sample.get - forAll(transactionGenerator) { tx: ErgoTransaction => - m = m.put(UnconfirmedTransaction(tx, None)) - } - // var prevMempoolSize = m.size - // val b = modifierWithTransactions(Some(m), None) - //todo: fix (m.size + b.transactions.get.size) shouldEqual prevMempoolSize - } - } -} - - diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala b/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala deleted file mode 100644 index 891c854c7e..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/mempool/MempoolTransactionsTest.scala +++ /dev/null @@ -1,155 +0,0 @@ -package scorex.testkit.properties.mempool - -import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks - -@SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) -trait MempoolTransactionsTest - extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers - with MemoryPoolTest { - - val transactionSeqGenerator: Gen[Seq[ErgoTransaction]] = Gen.nonEmptyContainerOf[Seq, ErgoTransaction](transactionGenerator) - val unconfirmedTxSeqGenerator: Gen[Seq[UnconfirmedTransaction]] = - transactionSeqGenerator.map(txs => txs.map(tx => UnconfirmedTransaction(tx, None))) - - property("Size of mempool should increase when adding a non-present transaction") { - forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTx) - m.size shouldEqual 1 - } - } - - property("Size of mempool should not increase when adding a present transaction") { - forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTx) - val m2: ErgoMemPool = m.put(unconfirmedTx) - m2.size shouldEqual 1 - } - } - - property("Size of mempool should increase when adding a collection of non-present transactions " + - "without duplicates (with check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should increase for a number of unique non-present transactions " + - "when adding a collection of non-present txs with duplicates (with check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs ++ unconfirmedTxs) - m.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should not increase when adding a collection of present transactions (with check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.put(unconfirmedTxs) - m2.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should increase when adding a collection of non-present transactions " + - "without duplicates (without check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should increase for a number of unique non-present transactions " + - "when adding a collection of non-present transactions with duplicates (without check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs ++ unconfirmedTxs) - m.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should not increase when adding a collection of present transactions (without check)") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.put(unconfirmedTxs) - m2.size shouldEqual unconfirmedTxs.size - } - } - - property("Size of mempool should decrease when removing a present transaction") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.remove(unconfirmedTxs.headOption.get.transaction) - m2.size shouldBe unconfirmedTxs.size - 1 - } - } - - property("Size of mempool should not decrease when removing a non-present transaction") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - val m2: ErgoMemPool = m.remove(unconfirmedTx.transaction) - m2.size shouldBe unconfirmedTxs.size - } - } - - property("Present transactions should be available by id") { - forAll(memPoolGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTx) - m.modifierById(unconfirmedTx.transaction.id).isDefined shouldBe true - } - } - - property("Non-present transactions should not be available by id") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.modifierById(unconfirmedTx.transaction.id).isDefined shouldBe false - } - } - - property("Mempool should contain present transactions") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.contains(unconfirmedTxs.headOption.get.transaction.id) shouldBe true - } - } - - property("Mempool should not contain non-present transactions") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.contains(unconfirmedTx.transaction.id) shouldBe false - } - } - - property("Present transactions should be obtained by their ids") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTxs :+ unconfirmedTx) - m.getAll(unconfirmedTxs.map(_.transaction.id)) sameElements unconfirmedTxs - } - } - - property("Non-present transactions should not be obtained by their ids") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], unconfirmedTx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTx) - m.getAll(unconfirmedTxs.map(_.transaction.id)).size shouldBe 0 - } - } - - property("Required number of transactions should be taken from mempool") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator, unconfirmedTxGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction], tx: UnconfirmedTransaction) => - val m: ErgoMemPool = mp.put(unconfirmedTxs :+ tx) - m.take(unconfirmedTxs.size).size shouldBe unconfirmedTxs.size - } - } - - property("Maximum number of transactions that can be taken should equals mempool size") { - forAll(memPoolGenerator, unconfirmedTxSeqGenerator) { (mp: ErgoMemPool, unconfirmedTxs: Seq[UnconfirmedTransaction]) => - val m: ErgoMemPool = mp.put(unconfirmedTxs) - m.take(unconfirmedTxs.size + 1).size shouldBe m.size - } - } -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala b/ergo-core/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala deleted file mode 100644 index 805550fffe..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/state/StateApplicationTest.scala +++ /dev/null @@ -1,106 +0,0 @@ -package scorex.testkit.properties.state - -import org.ergoplatform.modifiers.BlockSection -import org.ergoplatform.nodeView.state.{DigestState, ErgoState} -import org.scalacheck.Gen -import scala.collection.mutable.ListBuffer - - -trait StateApplicationTest[ST <: ErgoState[ST]] extends StateTests[ST] { - - lazy val stateGenWithValidModifier: Gen[(ST, BlockSection)] = { - stateGen.map { s => (s, semanticallyValidModifier(s)) } - } - - lazy val stateGenWithInvalidModifier: Gen[(ST, BlockSection)] = { - stateGen.map { s => (s, semanticallyInvalidModifier(s))} - } - - private def propertyNameGenerator(propName: String): String = s"StateTests: $propName" - - property(propertyNameGenerator("apply modifier")) { - forAll(stateGenWithValidModifier) { case (s, m) => - val ver = s.version - val sTry = s.applyModifier(m, None)(_ => ()) - sTry.isSuccess shouldBe true - sTry.get.version == ver shouldBe false - } - } - - property(propertyNameGenerator("do not apply same valid modifier twice")) { - forAll(stateGenWithValidModifier) { case (s, m) => - val ver = s.version - val sTry = s.applyModifier(m, None)(_ => ()) - sTry.isSuccess shouldBe true - val s2 = sTry.get - s2.version == ver shouldBe false - s2.applyModifier(m, None)(_ => ()).isSuccess shouldBe false - } - } - - property(propertyNameGenerator("do not apply invalid modifier")) { - forAll(stateGenWithInvalidModifier) { case (s, m) => - val sTry = s.applyModifier(m, None)(_ => ()) - sTry.isSuccess shouldBe false - } - } - - property(propertyNameGenerator("apply valid modifier after rollback")) { - forAll(stateGenWithValidModifier) { case (s, m) => - val ver = s.version - s.store.setKeepVersions(10) - val sTry = s.applyModifier(m, Some(0))(_ => ()) - sTry.isSuccess shouldBe true - val s2 = sTry.get - s2.version == ver shouldBe false - val ver2 = s2.version - - val s3 = s2.rollbackTo(ver).get - s3.version == ver shouldBe true - - val sTry2 = s3.applyModifier(m, None)(_ => ()) - sTry2.isSuccess shouldBe true - val s4 = sTry2.get - s4.version == ver shouldBe false - s4.version == ver2 shouldBe true - } - } - - property(propertyNameGenerator("application after rollback is possible")) { - forAll(stateGen) { s => - s.store.setKeepVersions(10) - val maxRollbackDepth = s match { - case ds: DigestState => - ds.store.rollbackVersions().size - case _ => - 10 - } - @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) - val rollbackDepth = Gen.chooseNum(1, maxRollbackDepth).sample.get - val buf = new ListBuffer[BlockSection]() - val ver = s.version - - val s2 = (0 until rollbackDepth).foldLeft(s) { case (state, _) => - val modifier = semanticallyValidModifier(state) - buf += modifier - val sTry = state.applyModifier(modifier, Some(rollbackDepth))(_ => ()) - sTry shouldBe 'success - sTry.get - } - - val lastVersion = s2.version - val rollbackTry = s2.rollbackTo(ver) - rollbackTry.toOption shouldBe defined - val s3 = rollbackTry.get - s3.version == ver shouldBe true - - val s4 = buf.foldLeft(s3) { case (state, m) => - val sTry = state.applyModifier(m, Some(0))(_ => ()) - sTry shouldBe 'success - sTry.get - } - - s4.version == lastVersion shouldBe true - } - } -} diff --git a/ergo-core/src/test/scala/scorex/testkit/properties/state/StateTests.scala b/ergo-core/src/test/scala/scorex/testkit/properties/state/StateTests.scala deleted file mode 100644 index 78c1452c8f..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/properties/state/StateTests.scala +++ /dev/null @@ -1,23 +0,0 @@ -package scorex.testkit.properties.state - -import org.ergoplatform.nodeView.state.ErgoState -import org.scalacheck.Gen -import org.scalatest.matchers.should.Matchers -import org.scalatest.propspec.AnyPropSpec -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import scorex.testkit.TestkitHelpers -import scorex.testkit.generators.{CoreGenerators, SemanticallyInvalidModifierProducer, SemanticallyValidModifierProducer} - -trait StateTests[ST <: ErgoState[ST]] - extends AnyPropSpec - with ScalaCheckPropertyChecks - with Matchers - with CoreGenerators - with TestkitHelpers - with SemanticallyValidModifierProducer[ST] - with SemanticallyInvalidModifierProducer[ST] { - - val checksToMake = 10 - - val stateGen: Gen[ST] -} diff --git a/ergo-core/src/test/scala/scorex/testkit/utils/AkkaFixture.scala b/ergo-core/src/test/scala/scorex/testkit/utils/AkkaFixture.scala deleted file mode 100644 index c3aa3b978e..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/utils/AkkaFixture.scala +++ /dev/null @@ -1,15 +0,0 @@ -package scorex.testkit.utils - -import java.util.concurrent.atomic.AtomicInteger - -import akka.actor.ActorSystem -import akka.testkit.{ImplicitSender, TestKit} - -object SysId { - private val i = new AtomicInteger() - def incrementAndGet(): Int = i.incrementAndGet() -} - -class AkkaFixture - extends TestKit(ActorSystem("WithIsoFix-%d".format(SysId.incrementAndGet()))) - with ImplicitSender diff --git a/ergo-core/src/test/scala/scorex/testkit/utils/NoShrink.scala b/ergo-core/src/test/scala/scorex/testkit/utils/NoShrink.scala deleted file mode 100644 index 4653280842..0000000000 --- a/ergo-core/src/test/scala/scorex/testkit/utils/NoShrink.scala +++ /dev/null @@ -1,7 +0,0 @@ -package scorex.testkit.utils - -import org.scalacheck.Shrink - -trait NoShrink { - protected implicit def noShrink[A]: Shrink[A] = Shrink(_ => Stream.empty) -} diff --git a/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala index 7d89b239a5..c48d4a6dbe 100644 --- a/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/EmissionApiRouteSpec.scala @@ -9,7 +9,7 @@ import io.circe.Json import io.circe.syntax._ import org.ergoplatform.http.api.EmissionApiRoute import org.ergoplatform.mining.emission.EmissionRules -import org.ergoplatform.settings.{ErgoSettings, ReemissionSettings} +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, ReemissionSettings} import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -24,7 +24,7 @@ class EmissionApiRouteSpec extends AnyFlatSpec implicit val timeout: RouteTestTimeout = RouteTestTimeout(15.seconds.dilated) - val ergoSettings: ErgoSettings = ErgoSettings.read() + val ergoSettings: ErgoSettings = ErgoSettingsReader.read() val coinEmission: EmissionRules = ergoSettings.chainSettings.emissionRules val reemissionSettings: ReemissionSettings = ergoSettings.chainSettings.reemission diff --git a/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala b/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala index 706ff37ddd..31fc10fa3b 100644 --- a/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/InfoApiRoutesSpec.scala @@ -16,8 +16,8 @@ import org.ergoplatform.local.ErgoStatsCollector.{GetNodeInfo, NodeInfo} import org.ergoplatform.local.ErgoStatsCollectorRef import org.ergoplatform.mining.difficulty.DifficultySerializer import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.ChangedHistory -import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.ChangedHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants.Difficulty import org.ergoplatform.utils.Stubs import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala index fb4956190f..c3a1c33851 100644 --- a/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/ScanApiRouteSpec.scala @@ -10,7 +10,7 @@ import org.ergoplatform.ErgoBox import org.ergoplatform.http.api.ScanEntities.{ScanIdBoxId, ScanIdWrapper} import org.ergoplatform.http.api.{ApiCodecs, ScanApiRoute} import org.ergoplatform.nodeView.wallet.scanning._ -import org.ergoplatform.settings.{Args, ErgoSettings} +import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.Stubs import org.ergoplatform.wallet.Constants.ScanId import org.scalatest.flatspec.AnyFlatSpec @@ -36,7 +36,7 @@ class ScanApiRouteSpec extends AnyFlatSpec val prefix = "/scan" - val ergoSettings: ErgoSettings = ErgoSettings.read( + val ergoSettings: ErgoSettings = ErgoSettingsReader.read( Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) val route: Route = ScanApiRoute(utxoReadersRef, ergoSettings).route diff --git a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala index acd2fd8de5..ff4b372c56 100644 --- a/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/ScriptApiRouteSpec.scala @@ -6,7 +6,7 @@ import akka.http.scaladsl.testkit.ScalatestRouteTest import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport import io.circe.Json import org.ergoplatform.{Pay2SAddress, Pay2SHAddress} -import org.ergoplatform.settings.{Args, ErgoSettings} +import org.ergoplatform.settings.{Args, ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.Stubs import io.circe.syntax._ import org.ergoplatform.http.api.ScriptApiRoute @@ -26,7 +26,7 @@ class ScriptApiRouteSpec extends AnyFlatSpec val prefix = "/script" - val ergoSettings: ErgoSettings = ErgoSettings.read( + val ergoSettings: ErgoSettings = ErgoSettingsReader.read( Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) val route: Route = ScriptApiRoute(digestReadersRef, settings).route diff --git a/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala b/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala index 3aa73d9dc1..f904eb5fff 100644 --- a/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala +++ b/src/test/scala/org/ergoplatform/http/routes/WalletApiRouteSpec.scala @@ -6,11 +6,11 @@ import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest} import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport import io.circe.syntax._ import io.circe.{Decoder, Json} -import org.ergoplatform.http.api.{ApiCodecs, WalletApiRoute} +import org.ergoplatform.http.api.{ApiCodecs, ApiNodeViewCodecs, WalletApiRoute} import org.ergoplatform.modifiers.mempool.ErgoTransaction import org.ergoplatform.nodeView.wallet.requests.{AssetIssueRequestEncoder, PaymentRequest, PaymentRequestEncoder, _} import org.ergoplatform.nodeView.wallet.{AugWalletTransaction, ErgoAddressJsonEncoder} -import org.ergoplatform.settings.{Args, Constants, ErgoSettings} +import org.ergoplatform.settings.{Args, Constants, ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.Stubs import org.ergoplatform.utils.generators.ErgoTransactionGenerators import org.ergoplatform.{ErgoAddress, Pay2SAddress} @@ -27,13 +27,14 @@ class WalletApiRouteSpec extends AnyFlatSpec with ScalatestRouteTest with Stubs with FailFastCirceSupport - with ApiCodecs { + with ApiCodecs + with ApiNodeViewCodecs { implicit val timeout: RouteTestTimeout = RouteTestTimeout(145.seconds) val prefix = "/wallet" - val ergoSettings: ErgoSettings = ErgoSettings.read( + val ergoSettings: ErgoSettings = ErgoSettingsReader.read( Args(userConfigPathOpt = Some("src/test/resources/application.conf"), networkTypeOpt = None)) val route: Route = WalletApiRoute(digestReadersRef, nodeViewRef, settings).route val failingNodeViewRef = system.actorOf(NodeViewStub.failingProps()) @@ -44,7 +45,7 @@ class WalletApiRouteSpec extends AnyFlatSpec implicit val paymentRequestEncoder: PaymentRequestEncoder = new PaymentRequestEncoder(ergoSettings) implicit val assetIssueRequestEncoder: AssetIssueRequestEncoder = new AssetIssueRequestEncoder(ergoSettings) implicit val requestsHolderEncoder: RequestsHolderEncoder = new RequestsHolderEncoder(ergoSettings) - implicit val addressJsonDecoder: Decoder[ErgoAddress] = ErgoAddressJsonEncoder(settings).decoder + implicit val addressJsonDecoder: Decoder[ErgoAddress] = ErgoAddressJsonEncoder(settings.chainSettings).decoder val paymentRequest = PaymentRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), 100L, Seq.empty, Map.empty) val assetIssueRequest = AssetIssueRequest(Pay2SAddress(Constants.FalseLeaf)(addressEncoder), None, 100L, "TEST", "Test", 8) diff --git a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala index f018569c5e..0b0022b5c9 100644 --- a/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala +++ b/src/test/scala/org/ergoplatform/local/MempoolAuditorSpec.scala @@ -4,9 +4,9 @@ import akka.actor.{ActorRef, ActorSystem} import akka.testkit.{TestActorRef, TestProbe} import org.ergoplatform.ErgoAddressEncoder import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{FailedTransaction, RecheckMempool, SuccessfulTransaction} +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{FailedTransaction, RecheckMempool, SuccessfulTransaction} import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{LocallyGeneratedTransaction, RecheckedTransactions} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.ProcessingOutcome import org.ergoplatform.nodeView.state.ErgoState import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.{Algos, Constants, ErgoSettings} diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala index 0b4f9cd0a7..9fb5a6df9f 100644 --- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorPropSpec.scala @@ -1,7 +1,7 @@ package org.ergoplatform.mining import org.ergoplatform.ErgoTreePredef -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.ErgoStateContext import org.ergoplatform.settings.MonetarySettings import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} @@ -199,7 +199,7 @@ class CandidateGeneratorPropSpec extends ErgoPropertyTest { val bh = boxesHolderGen.sample.get var us = createUtxoState(bh, parameters) - val height = ErgoHistory.EmptyHistoryHeight + val height = EmptyHistoryHeight val ms = MonetarySettings(minerRewardDelay = delta) val st = settings.copy(chainSettings = settings.chainSettings.copy(monetary = ms)) @@ -248,7 +248,7 @@ class CandidateGeneratorPropSpec extends ErgoPropertyTest { Gen.nonEmptyListOf(validErgoTransactionGenTemplate(minAssets = 0, propositionGen = feeProp)) ) { btxs => val blockTxs = btxs.map(_._2) - val height = ErgoHistory.EmptyHistoryHeight + val height = EmptyHistoryHeight val txs = CandidateGenerator.collectRewards( us.emissionBoxOpt, height, diff --git a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala index 148d5ebffb..d94938f591 100644 --- a/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/CandidateGeneratorSpec.scala @@ -9,12 +9,12 @@ import org.ergoplatform.mining.CandidateGenerator.{Candidate, GenerateCandidate} import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers} import org.ergoplatform.nodeView.history.ErgoHistoryReader import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef} -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.ErgoTestHelpers import org.ergoplatform.{ErgoBox, ErgoBoxCandidate, ErgoTreePredef, Input} import org.scalatest.concurrent.Eventually @@ -34,7 +34,7 @@ class CandidateGeneratorSpec extends AnyFlatSpec with ErgoTestHelpers with Event private val blockValidationDelay: FiniteDuration = 2.seconds val defaultSettings: ErgoSettings = { - val empty = ErgoSettings.read() + val empty = ErgoSettingsReader.read() val nodeSettings = empty.nodeSettings.copy( mining = true, stateType = StateType.Utxo, diff --git a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala index 25258277e3..dcfb805a23 100644 --- a/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala +++ b/src/test/scala/org/ergoplatform/mining/ErgoMinerSpec.scala @@ -10,14 +10,14 @@ import org.ergoplatform.mining.ErgoMiner.StartMining import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction, UnsignedErgoTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.FullBlockApplied +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.FullBlockApplied import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction import org.ergoplatform.nodeView.ErgoReadersHolder.{GetReaders, Readers} import org.ergoplatform.nodeView.history.ErgoHistoryReader import org.ergoplatform.nodeView.state._ import org.ergoplatform.nodeView.wallet._ import org.ergoplatform.nodeView.{ErgoNodeViewRef, ErgoReadersHolderRef} -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.ErgoTestHelpers import org.ergoplatform.utils.generators.ValidBlocksGenerators import org.ergoplatform.wallet.interpreter.ErgoInterpreter @@ -47,7 +47,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen await(minerRef.askWithStatus(GenerateCandidate(mandatoryTransactions, reply = true)).mapTo[Candidate].map(_.externalVersion)) val defaultSettings: ErgoSettings = { - val empty = ErgoSettings.read() + val empty = ErgoSettingsReader.read() val nodeSettings = empty.nodeSettings.copy(mining = true, stateType = StateType.Utxo, @@ -376,7 +376,7 @@ class ErgoMinerSpec extends AnyFlatSpec with ErgoTestHelpers with ValidBlocksGen system.eventStream.subscribe(testProbe.ref, newBlockSignal) val forkSettings: ErgoSettings = { - val empty = ErgoSettings.read() + val empty = ErgoSettingsReader.read() val nodeSettings = empty.nodeSettings.copy(mining = true, stateType = StateType.Utxo, diff --git a/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala b/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala index ea2a976724..6eabd252ad 100644 --- a/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala +++ b/src/test/scala/org/ergoplatform/modifiers/history/PoPowAlgosSpec.scala @@ -1,6 +1,6 @@ package org.ergoplatform.modifiers.history -import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowProof, PoPowHeader, PoPowParams} +import org.ergoplatform.modifiers.history.popow.{NipopowAlgos, NipopowErgoAlgos, NipopowProof, PoPowHeader, PoPowParams} import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.utils.generators.ChainGenerator @@ -127,7 +127,7 @@ class PoPowAlgosSpec extends AnyPropSpec with Matchers with HistoryTestHelpers w val h = generateHistory(true, StateType.Digest, false, 10000, 10000, 10, None) val hr = applyChain(h, blocksChain) - val proof1 = nipopowAlgos.prove(hr)(poPowParams).get + val proof1 = NipopowErgoAlgos.prove(hr, chainSettings = settings.chainSettings)(poPowParams).get proof0.suffixHead.id shouldBe proof1.suffixHead.id proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id) @@ -145,12 +145,12 @@ class PoPowAlgosSpec extends AnyPropSpec with Matchers with HistoryTestHelpers w val h = generateHistory(true, StateType.Digest, false, 10000, 10000, 10, None) val hr = applyChain(h, blocksChain.take(at)) - val proof0 = nipopowAlgos.prove(hr, None)(poPowParams).get + val proof0 = NipopowErgoAlgos.prove(hr, None, chainSettings = settings.chainSettings)(poPowParams).get val id = proof0.suffixHead.header.id val hrf = applyChain(hr, blocksChain.drop(at)) - val proof1 = nipopowAlgos.prove(hrf, Some(id))(poPowParams).get + val proof1 = NipopowErgoAlgos.prove(hrf, Some(id), chainSettings = settings.chainSettings)(poPowParams).get proof0.suffixHead.id shouldBe proof1.suffixHead.id proof0.suffixTail.map(_.id) shouldBe proof1.suffixTail.map(_.id) diff --git a/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala b/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala index 2430aa7728..efb8d45762 100644 --- a/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala +++ b/src/test/scala/org/ergoplatform/network/ErgoNodeViewSynchronizerSpecification.scala @@ -4,14 +4,14 @@ import akka.actor.{ActorRef, ActorSystem, Cancellable, Props} import akka.testkit.TestProbe import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} import org.ergoplatform.modifiers.{BlockSection, ErgoFullBlock} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._ import org.ergoplatform.nodeView.ErgoNodeViewHolder import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryReader, ErgoSyncInfoMessageSpec, ErgoSyncInfoV2} import org.ergoplatform.nodeView.mempool.ErgoMemPool import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.nodeView.state.{StateType, UtxoState} import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader} import org.ergoplatform.utils.HistoryTestHelpers import org.ergoplatform.wallet.utils.FileUtils import org.scalacheck.Gen @@ -126,7 +126,7 @@ class ErgoNodeViewSynchronizerSpecification extends HistoryTestHelpers with Matc val h = localHistoryGen.sample.get @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) val s = localStateGen.sample.get - val settings = ErgoSettings.read() + val settings = ErgoSettingsReader.read() val pool = ErgoMemPool.empty(settings) implicit val ec: ExecutionContextExecutor = system.dispatcher val ncProbe = TestProbe("NetworkControllerProbe") diff --git a/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala b/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala index 29e67176bd..673ad6b6ed 100644 --- a/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/ErgoModifiersCacheSpec.scala @@ -2,7 +2,7 @@ package org.ergoplatform.nodeView import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions} -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers} import scorex.crypto.hash.Blake2b256 @@ -64,7 +64,7 @@ class ErgoModifiersCacheSpec extends ErgoPropertyTest with HistoryTestHelpers { val c1 = modifiersCache.popCandidate(history0).value c1.isInstanceOf[Header] shouldBe true val h1 = c1.asInstanceOf[Header] - h1.height shouldBe ErgoHistory.GenesisHeight + h1.height shouldBe GenesisHeight val history1 = history0.append(c1).get._1 diff --git a/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala b/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala index 9311d13c78..829084d463 100644 --- a/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala +++ b/src/test/scala/org/ergoplatform/nodeView/NodeViewSynchronizerTests.scala @@ -5,7 +5,7 @@ import akka.testkit.TestProbe import org.ergoplatform.modifiers.BlockSection import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._ import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetNodeViewChanges, ModifiersFromRemote} import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoSyncInfo, ErgoSyncInfoMessageSpec} import org.ergoplatform.nodeView.mempool.ErgoMemPool diff --git a/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala index 40feb58cef..f8df13aab8 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/BlockSectionValidationSpecification.scala @@ -5,6 +5,7 @@ import org.ergoplatform.modifiers.history._ import org.ergoplatform.modifiers.history.extension.Extension import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.nodeView.state.StateType +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.utils.HistoryTestHelpers import scorex.core.consensus.ModifierSemanticValidity import scorex.crypto.hash.Blake2b256 @@ -75,7 +76,7 @@ class BlockSectionValidationSpecification extends HistoryTestHelpers { history.writeMinimalFullBlockHeight(history.bestHeaderOpt.get.height + 1) history.isHeadersChainSyncedVar = true history.applicableTry(section) shouldBe 'failure - history.writeMinimalFullBlockHeight(ErgoHistory.GenesisHeight) + history.writeMinimalFullBlockHeight(GenesisHeight) // should not be able to apply if corresponding header is marked as invalid history.applicableTry(section) shouldBe 'success diff --git a/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala index b2cbb964ca..f4a7e10894 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/NonVerifyADHistorySpecification.scala @@ -6,6 +6,7 @@ import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.history.popow.NipopowAlgos import org.ergoplatform.modifiers.history.HeaderChain import org.ergoplatform.nodeView.state.StateType +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.settings.Algos import org.ergoplatform.utils.HistoryTestHelpers import scorex.crypto.hash.Digest32 @@ -268,7 +269,7 @@ class NonVerifyADHistorySpecification extends HistoryTestHelpers { val chain = genHeaderChain(BlocksInChain, history, diffBitsOpt = None, useRealTs = false) chain.headers.foreach { header => - val inHeight = history.heightOf(header.parentId).getOrElse(ErgoHistory.EmptyHistoryHeight) + val inHeight = history.heightOf(header.parentId).getOrElse(EmptyHistoryHeight) history.contains(header) shouldBe false history.applicable(header) shouldBe true diff --git a/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala index 3903251054..3d93a5f0ad 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/UtxoSetSnapshotProcessorSpecification.scala @@ -1,6 +1,7 @@ package org.ergoplatform.nodeView.history import org.ergoplatform.nodeView.history.storage.HistoryStorage +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.history.storage.modifierprocessors.UtxoSetSnapshotProcessor import org.ergoplatform.nodeView.state.{StateType, UtxoState} import org.ergoplatform.settings.{Algos, ErgoSettings} @@ -19,7 +20,7 @@ class UtxoSetSnapshotProcessorSpecification extends HistoryTestHelpers { val epochLength = 20 val utxoSetSnapshotProcessor = new UtxoSetSnapshotProcessor { - var minimalFullBlockHeightVar = ErgoHistory.GenesisHeight + var minimalFullBlockHeightVar = GenesisHeight override protected val settings: ErgoSettings = s.copy(chainSettings = s.chainSettings.copy(voting = s.chainSettings.voting.copy(votingLength = epochLength))) override protected val historyStorage: HistoryStorage = HistoryStorage(settings) diff --git a/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala index 0240d00afb..0a645b56a4 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/VerifyADHistorySpecification.scala @@ -3,6 +3,7 @@ package org.ergoplatform.nodeView.history import org.ergoplatform.modifiers.history.extension.Extension import org.ergoplatform.modifiers.history.HeaderChain import org.ergoplatform.modifiers.history.header.Header +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.modifiers.{ErgoFullBlock, BlockSection} import org.ergoplatform.nodeView.ErgoModifiersCache import org.ergoplatform.nodeView.state.StateType @@ -19,7 +20,7 @@ class VerifyADHistorySpecification extends HistoryTestHelpers with NoShrink { type PM = BlockSection private def genHistory(blocksNum: Int = 0, - minFullHeight: Option[Int] = Some(ErgoHistory.GenesisHeight)): (ErgoHistory, Seq[ErgoFullBlock]) = { + minFullHeight: Option[Int] = Some(GenesisHeight)): (ErgoHistory, Seq[ErgoFullBlock]) = { val inHistory = generateHistory(verifyTransactions = true, StateType.Digest, PoPoWBootstrap = false, BlocksToKeep) minFullHeight.foreach { h => inHistory.writeMinimalFullBlockHeight(h) diff --git a/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala index a377e8a2e7..4bbab55b42 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/extra/ExtraIndexerSpecification.scala @@ -11,9 +11,10 @@ import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.history.popow.NipopowAlgos import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.history.extra.IndexedErgoAddressSerializer.hashErgoTree import org.ergoplatform.nodeView.history.extra.SegmentSerializer.{boxSegmentId, txSegmentId} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.SortingOption import org.ergoplatform.nodeView.state._ import org.ergoplatform.settings.{ErgoSettings, NetworkType, NipopowSettings, NodeConfigurationSettings, UtxoSettings} import org.ergoplatform.utils.{ErgoPropertyTest, ErgoTestHelpers, HistoryTestHelpers} @@ -310,7 +311,7 @@ object ChainGenerator extends ErgoTestHelpers { acc: Seq[ModifierId])(history: ErgoHistory): Seq[ModifierId] = { val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime) if (time < System.currentTimeMillis()) { - val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight), + val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(GenesisHeight), initBox, state.stateContext) val candidate = genCandidate(defaultProver.hdPubKeys.head.key, last, time, txs, state)(history) diff --git a/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala b/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala index 7020d1fee7..bd83682256 100644 --- a/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/history/storage/HistoryStorageSpec.scala @@ -3,7 +3,7 @@ package org.ergoplatform.nodeView.history.storage import org.ergoplatform.modifiers.BlockSection import org.ergoplatform.modifiers.history.ADProofs import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.settings.Algos import org.ergoplatform.utils.HistoryTestHelpers import org.scalacheck.Gen @@ -17,7 +17,7 @@ class HistoryStorageSpec extends HistoryTestHelpers { property("Write Read Remove") { val headers: Array[Header] = Gen.listOfN(20, defaultHeaderGen).sample.get.toArray val modifiers: Array[ADProofs] = Gen.listOfN(20, randomADProofsGen).sample.get.toArray - def validityKey(id: ModifierId) = ByteArrayWrapper(Algos.hash("validity".getBytes(ErgoHistory.CharsetName) ++ idToBytes(id))) + def validityKey(id: ModifierId) = ByteArrayWrapper(Algos.hash("validity".getBytes(CharsetName) ++ idToBytes(id))) val indexes = headers.flatMap(h => Array(validityKey(h.id) -> Array(1.toByte))) db.insert(indexes, (headers ++ modifiers).asInstanceOf[Array[BlockSection]]) shouldBe 'success diff --git a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala index 38aaa799d3..159129b456 100644 --- a/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/mempool/ErgoMemPoolSpec.scala @@ -1,9 +1,8 @@ package org.ergoplatform.nodeView.mempool import org.ergoplatform.{ErgoBoxCandidate, Input} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.{SortingOption, ProcessingOutcome} import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.ErgoSettings import org.ergoplatform.utils.ErgoTestHelpers diff --git a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala index e166806043..5eaf57d740 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/ErgoStateSpecification.scala @@ -4,7 +4,7 @@ import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.settings.{Args, ErgoSettings} +import org.ergoplatform.settings.{Args, ErgoSettingsReader} import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} import org.ergoplatform.wallet.boxes.ErgoBoxSerializer import org.scalacheck.Gen @@ -66,7 +66,7 @@ class ErgoStateSpecification extends ErgoPropertyTest { } property("generateGenesisUtxoState & generateGenesisDigestState are compliant") { - val settings = ErgoSettings.read(Args.empty) + val settings = ErgoSettingsReader.read(Args.empty) val dir = createTempDir val rootHash = createUtxoState(settings)._1.rootDigest val expectedRootHash = ErgoState.generateGenesisDigestState(dir, settings).rootDigest diff --git a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala index e3dc146a8c..1811e9b1d3 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/UtxoStateSpecification.scala @@ -9,7 +9,7 @@ import org.ergoplatform.modifiers.history.extension.Extension import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.history.{ADProofs, BlockTransactions} import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.Constants import org.ergoplatform.utils.{ErgoPropertyTest, RandomWrapper} @@ -62,7 +62,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera property("Founders should be able to spend genesis founders box") { var (us, bh) = createUtxoState(settings) val foundersBox = genesisBoxes.last - var height: Int = ErgoHistory.GenesisHeight + var height: Int = GenesisHeight val settingsPks = settings.chainSettings.foundersPubkeys .map(str => groupElemFromBytes(Base16.decode(str).get)) @@ -160,7 +160,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera property("proofsForTransactions") { var (us: UtxoState, bh) = createUtxoState(settings) - var height: Int = ErgoHistory.GenesisHeight + var height: Int = GenesisHeight forAll(defaultHeaderGen) { header => val t = validTransactionsFromBoxHolder(bh, new RandomWrapper(Some(height))) val txs = t._1 @@ -184,7 +184,7 @@ class UtxoStateSpecification extends ErgoPropertyTest with ErgoTransactionGenera var bh = BoxHolder(Seq(genesisEmissionBox)) var us = createUtxoState(bh, parameters) - var height: Int = ErgoHistory.GenesisHeight + var height: Int = GenesisHeight // generate chain of correct full blocks val chain = (0 until 10) map { _ => val header = defaultHeaderGen.sample.value diff --git a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala index fe1933fad9..765e0b2444 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedDigestState.scala @@ -1,6 +1,6 @@ package org.ergoplatform.nodeView.state.wrapped -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier._ import org.ergoplatform.ErgoLikeContext.Height import org.ergoplatform.modifiers.BlockSection import org.ergoplatform.nodeView.state.DigestState diff --git a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala index d747a4b5be..114d6a1243 100644 --- a/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala +++ b/src/test/scala/org/ergoplatform/nodeView/state/wrapped/WrappedUtxoState.scala @@ -4,7 +4,7 @@ import java.io.File import akka.actor.ActorRef import org.ergoplatform.ErgoBox -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier._ import org.ergoplatform.ErgoLikeContext.Height import org.ergoplatform.modifiers.BlockSection import org.ergoplatform.nodeView.state._ diff --git a/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala index 83e9243ad9..93f1563d58 100644 --- a/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/viewholder/ErgoNodeViewHolderSpec.scala @@ -4,17 +4,18 @@ import java.io.File import org.ergoplatform.ErgoBoxCandidate import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.mempool.UnconfirmedTransaction -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.StateType.Utxo import org.ergoplatform.nodeView.state._ import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.settings.{Algos, Constants, ErgoSettings} import org.ergoplatform.utils.{ErgoPropertyTest, HistoryTestHelpers, NodeViewTestConfig, NodeViewTestOps, TestCase} import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages._ -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._ import org.ergoplatform.nodeView.ErgoNodeViewHolder import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.ChainProgress -import org.ergoplatform.nodeView.mempool.ErgoMemPool.ProcessingOutcome.Accepted +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier.LocallyGeneratedModifier +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.ProcessingOutcome.Accepted import scorex.crypto.authds.{ADKey, SerializedAdProof} import scorex.testkit.utils.NoShrink import scorex.util.{ModifierId, bytesToId} @@ -55,7 +56,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val block = validFullBlock(None, us, bh) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -63,8 +64,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi nodeViewHolderRef ! LocallyGeneratedModifier(block.header) expectMsgType[SyntacticallySuccessfulModifier] - getHistoryHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) + getHistoryHeight shouldBe GenesisHeight + getHeightOf(block.header.id) shouldBe Some(GenesisHeight) getLastHeadersLength(10) shouldBe 1 getBestHeaderOpt shouldBe Some(block.header) } @@ -76,7 +77,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val block = validFullBlock(Some(parentBlock), us, bh) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -317,7 +318,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val (us, bh) = createUtxoState(fixture.settings) val block = validFullBlock(None, us, bh) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[RecoverableFailedModification]) subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -327,8 +328,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi nodeViewHolderRef ! LocallyGeneratedModifier(block.header) expectMsgType[SyntacticallySuccessfulModifier] val currentHeight = getHistoryHeight - currentHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) + currentHeight shouldBe GenesisHeight + getHeightOf(block.header.id) shouldBe Some(GenesisHeight) val randomId = modifierIdGen.sample.value val recoverableTxs = block.blockTransactions.copy(headerId = randomId) @@ -371,7 +372,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val block = validFullBlock(None, us, bh) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[RecoverableFailedModification]) subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -404,7 +405,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val block = validFullBlock(None, us, bh) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[RecoverableFailedModification]) subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -414,7 +415,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi nodeViewHolderRef ! LocallyGeneratedModifier(block.header) expectMsgType[SyntacticallyFailedModification] getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight } private val t15 = TestCase("apply genesis block header if it's equal to genesisId from config") { fixture => @@ -424,7 +425,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi updateConfig(genesisIdConfig(Some(block.header.id))) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[RecoverableFailedModification]) subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -432,8 +433,8 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi nodeViewHolderRef ! LocallyGeneratedModifier(block.header) expectMsgType[SyntacticallySuccessfulModifier] - getHistoryHeight shouldBe ErgoHistory.GenesisHeight - getHeightOf(block.header.id) shouldBe Some(ErgoHistory.GenesisHeight) + getHistoryHeight shouldBe GenesisHeight + getHeightOf(block.header.id) shouldBe Some(GenesisHeight) } private val t16 = TestCase("apply forks that include genesis block") { fixture => @@ -473,7 +474,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi val header = validFullBlock(None, us, bh).header.copy(parentId = bytesToId(Array.fill(32)(9: Byte))) getBestHeaderOpt shouldBe None - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight subscribeEvents(classOf[RecoverableFailedModification]) subscribeEvents(classOf[SyntacticallySuccessfulModifier]) @@ -481,7 +482,7 @@ class ErgoNodeViewHolderSpec extends ErgoPropertyTest with HistoryTestHelpers wi nodeViewHolderRef ! LocallyGeneratedModifier(header) expectMsgType[SyntacticallyFailedModification] - getHistoryHeight shouldBe ErgoHistory.EmptyHistoryHeight + getHistoryHeight shouldBe EmptyHistoryHeight getHeightOf(header.id) shouldBe None } diff --git a/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala b/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala index 621a2119dd..7572e87ded 100644 --- a/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala +++ b/src/test/scala/org/ergoplatform/nodeView/viewholder/PrunedNodeViewHolderSpec.scala @@ -5,10 +5,10 @@ import org.ergoplatform.mining.DefaultFakePowScheme import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.nodeView.state.{DigestState, StateType} -import org.ergoplatform.settings.{ErgoSettings, VotingSettings} +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, VotingSettings} import org.ergoplatform.utils.fixtures.NodeViewFixture import org.ergoplatform.utils.{ErgoPropertyTest, NodeViewTestOps} -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedModifier +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier._ import scorex.testkit.utils.NoShrink import scala.concurrent.duration._ @@ -20,7 +20,7 @@ class PrunedNodeViewHolderSpec extends ErgoPropertyTest with NodeViewTestOps wit private val BlockInterval = 2.minutes def prunedSettings(blocksToKeep: Int): ErgoSettings = { - val defaultSettings = ErgoSettings.read() + val defaultSettings = ErgoSettingsReader.read() defaultSettings.copy( chainSettings = defaultSettings.chainSettings.copy( powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n), diff --git a/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala b/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala index d9b07a50e7..8a20ca97f2 100644 --- a/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala +++ b/src/test/scala/org/ergoplatform/sanity/ErgoSanityDigest.scala @@ -5,14 +5,14 @@ import akka.testkit.TestProbe import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.HeaderSerializer -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool} +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{ChangedHistory, ChangedMempool} import org.ergoplatform.network.ErgoSyncTracker import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec import org.ergoplatform.nodeView.mempool.ErgoMemPool import org.ergoplatform.nodeView.state.wrapped.{WrappedDigestState, WrappedUtxoState} import org.ergoplatform.nodeView.state.{DigestState, StateType} import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.settings.ErgoSettingsReader import org.scalacheck.Gen import scorex.core.idToBytes import scorex.core.network.{ConnectedPeer, DeliveryTracker} @@ -58,7 +58,7 @@ class ErgoSanityDigest extends ErgoSanity[DIGEST_ST] { val h = historyGen.sample.get @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) val s = stateGen.sample.get - val settings = ErgoSettings.read() + val settings = ErgoSettingsReader.read() val pool = ErgoMemPool.empty(settings) val v = h.bestFullBlockIdOpt.orElse(h.bestHeaderIdOpt) v.foreach(id => s.store.update(idToBytes(id), Seq(), Seq()).get) diff --git a/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala b/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala index ef6107e35b..2653a195cb 100644 --- a/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala +++ b/src/test/scala/org/ergoplatform/sanity/ErgoSanityUTXO.scala @@ -5,14 +5,14 @@ import akka.testkit.TestProbe import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages.{ChangedHistory, ChangedMempool} +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages.{ChangedHistory, ChangedMempool} import org.ergoplatform.network.ErgoSyncTracker import org.ergoplatform.nodeView.history.ErgoSyncInfoMessageSpec import org.ergoplatform.nodeView.mempool.ErgoMemPool import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.sanity.ErgoSanity._ -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.settings.ErgoSettingsReader import org.ergoplatform.utils.ErgoTestHelpers import org.scalacheck.Gen import scorex.core.network.{ConnectedPeer, DeliveryTracker} @@ -55,7 +55,7 @@ class ErgoSanityUTXO extends ErgoSanity[UTXO_ST] with ErgoTestHelpers { val h = historyGen.sample.get @SuppressWarnings(Array("org.wartremover.warts.OptionPartial")) val s = stateGen.sample.get - val settings = ErgoSettings.read() + val settings = ErgoSettingsReader.read() val pool = ErgoMemPool.empty(settings) implicit val ec: ExecutionContextExecutor = system.dispatcher val ncProbe = TestProbe("NetworkControllerProbe") diff --git a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala index 016696d708..f0be0e97a2 100644 --- a/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala +++ b/src/test/scala/org/ergoplatform/serialization/JsonSerializationSpec.scala @@ -4,7 +4,7 @@ import io.circe.syntax._ import io.circe.{ACursor, Decoder, Encoder, Json} import org.ergoplatform.ErgoBox import org.ergoplatform.ErgoBox.{AdditionalRegisters, NonMandatoryRegisterId} -import org.ergoplatform.http.api.ApiCodecs +import org.ergoplatform.http.api.{ApiCodecs, ApiNodeViewCodecs} import org.ergoplatform.http.api.ApiEncoderOption.HideDetails.implicitValue import org.ergoplatform.http.api.ApiEncoderOption.{Detalization, ShowDetails} import org.ergoplatform.modifiers.ErgoFullBlock @@ -12,7 +12,7 @@ import org.ergoplatform.modifiers.history.popow.NipopowProof import org.ergoplatform.modifiers.mempool.UnsignedErgoTransaction import org.ergoplatform.nodeView.wallet.requests._ import org.ergoplatform.sdk.wallet.secrets.{DhtSecretKey, DlogSecretKey} -import org.ergoplatform.settings.{Algos, ErgoSettings} +import org.ergoplatform.settings.{Algos, ErgoSettingsReader} import org.ergoplatform.utils.ErgoPropertyTest import org.ergoplatform.utils.generators.WalletGenerators import org.ergoplatform.wallet.Constants.ScanId @@ -24,7 +24,7 @@ import sigmastate.Values.{ErgoTree, EvaluatedValue} import scala.util.Random -class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with ApiCodecs { +class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with ApiCodecs with ApiNodeViewCodecs { property("ErgoFullBlock should be encoded into JSON and decoded back correctly") { @@ -52,7 +52,7 @@ class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with } property("PaymentRequest should be serialized to json") { - val ergoSettings = ErgoSettings.read() + val ergoSettings = ErgoSettingsReader.read() implicit val requestEncoder: Encoder[PaymentRequest] = new PaymentRequestEncoder(ergoSettings) implicit val requestDecoder: Decoder[PaymentRequest] = new PaymentRequestDecoder(ergoSettings) forAll(paymentRequestGen) { request => @@ -88,7 +88,7 @@ class JsonSerializationSpec extends ErgoPropertyTest with WalletGenerators with } property("AssetIssueRequest should be serialized to json") { - val ergoSettings = ErgoSettings.read() + val ergoSettings = ErgoSettingsReader.read() implicit val requestEncoder: Encoder[AssetIssueRequest] = new AssetIssueRequestEncoder(ergoSettings) implicit val requestDecoder: Decoder[AssetIssueRequest] = new AssetIssueRequestDecoder(ergoSettings) forAll(assetIssueRequestGen) { request => diff --git a/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala b/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala index a792c82c3e..be26e2d5e3 100644 --- a/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala +++ b/src/test/scala/org/ergoplatform/serialization/SerializationTests.scala @@ -6,10 +6,11 @@ import org.ergoplatform.modifiers.history.extension.ExtensionSerializer import org.ergoplatform.modifiers.history.header.{Header, HeaderSerializer} import org.ergoplatform.modifiers.history.popow.NipopowProofSerializer import org.ergoplatform.modifiers.mempool.ErgoTransactionSerializer +import org.ergoplatform.network.ErgoNodeViewSynchronizer import org.ergoplatform.nodeView.history.ErgoSyncInfoSerializer import org.ergoplatform.nodeView.wallet.persistence.WalletDigestSerializer import org.ergoplatform.nodeView.state.ErgoStateContextSerializer -import org.ergoplatform.settings.{Constants, ErgoValidationSettings, ErgoValidationSettingsSerializer, ErgoValidationSettingsUpdateSerializer} +import org.ergoplatform.settings.{ErgoValidationSettings, ErgoValidationSettingsSerializer, ErgoValidationSettingsUpdateSerializer} import org.ergoplatform.utils.ErgoPropertyTest import org.ergoplatform.utils.generators.WalletGenerators import org.scalacheck.Gen @@ -30,7 +31,7 @@ class SerializationTests extends ErgoPropertyTest with WalletGenerators with sco property("Serializers should be defined for all block sections") { val block = invalidErgoFullBlockGen.sample.get block.toSeq.foreach { s => - Constants.modifierSerializers.get(s.modifierTypeId) should not be None + ErgoNodeViewSynchronizer.modifierSerializers.get(s.modifierTypeId) should not be None } } diff --git a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala index e222ec2d88..fe815bd734 100644 --- a/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala +++ b/src/test/scala/org/ergoplatform/settings/ErgoSettingsSpecification.scala @@ -1,6 +1,6 @@ package org.ergoplatform.settings -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.SortingOption import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.utils.ErgoPropertyTest import scorex.core.settings.RESTApiSettings @@ -14,12 +14,12 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { private val txSizeLimit = initSettings.nodeSettings.maxTransactionSize property("should keep data user home by default") { - val settings = ErgoSettings.read() + val settings = ErgoSettingsReader.read() settings.directory shouldBe System.getProperty("user.dir") + "/.ergo_test/data" } property("should read default settings") { - val settings = ErgoSettings.read() + val settings = ErgoSettingsReader.read() settings.nodeSettings shouldBe NodeConfigurationSettings( StateType.Utxo, verifyTransactions = true, @@ -68,7 +68,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { } property("should read user settings from json file") { - val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.json"), None)) + val settings = ErgoSettingsReader.read(Args(Some("src/test/resources/settings.json"), None)) settings.nodeSettings shouldBe NodeConfigurationSettings( StateType.Utxo, verifyTransactions = true, @@ -110,7 +110,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { } property("should read user settings from HOCON file") { - val settings = ErgoSettings.read(Args(Some("src/test/resources/settings.conf"), None)) + val settings = ErgoSettingsReader.read(Args(Some("src/test/resources/settings.conf"), None)) settings.nodeSettings shouldBe NodeConfigurationSettings( StateType.Utxo, verifyTransactions = true, @@ -162,7 +162,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { "http://example.com?foo=bar" ).map(new URL(_)) - invalidUrls.forall(ErgoSettings.invalidRestApiUrl) shouldBe true + invalidUrls.forall(ErgoSettingsReader.invalidRestApiUrl) shouldBe true val validUrls = List( @@ -172,7 +172,7 @@ class ErgoSettingsSpecification extends ErgoPropertyTest { "http://82.90.21.31:80" ).map(new URL(_)) - validUrls.forall(url => !ErgoSettings.invalidRestApiUrl(url)) shouldBe true + validUrls.forall(url => !ErgoSettingsReader.invalidRestApiUrl(url)) shouldBe true } } diff --git a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala index 7fb07b62f9..a4b4f81fca 100644 --- a/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala +++ b/src/test/scala/org/ergoplatform/tools/ChainGenerator.scala @@ -9,8 +9,8 @@ import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.history.popow.NipopowAlgos import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} import org.ergoplatform.nodeView.history.ErgoHistory -import org.ergoplatform.nodeView.history.ErgoHistory.Height -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.SortingOption import org.ergoplatform.nodeView.state._ import org.ergoplatform.settings._ import org.ergoplatform.utils.{ErgoTestHelpers, HistoryTestHelpers} @@ -32,7 +32,7 @@ import scala.util.Try object ChainGenerator extends App with ErgoTestHelpers { val realNetworkSetting = { - val initSettings = ErgoSettings.read(Args(None, Some(NetworkType.TestNet))) + val initSettings = ErgoSettingsReader.read(Args(None, Some(NetworkType.TestNet))) initSettings.copy(chainSettings = initSettings.chainSettings.copy(genesisId = None)) } @@ -94,7 +94,7 @@ object ChainGenerator extends App with ErgoTestHelpers { acc: Seq[ModifierId]): Seq[ModifierId] = { val time: Long = last.map(_.timestamp + blockInterval.toMillis).getOrElse(startTime) if (time < System.currentTimeMillis()) { - val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(ErgoHistory.GenesisHeight), + val (txs, lastOut) = genTransactions(last.map(_.height).getOrElse(GenesisHeight), initBox, state.stateContext) val candidate = genCandidate(prover.hdPubKeys.head.key, last, time, txs, state) diff --git a/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala b/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala index 8c38a167e4..bcb0a8ff64 100644 --- a/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala +++ b/src/test/scala/org/ergoplatform/tools/DifficultyControlSimulator.scala @@ -2,8 +2,8 @@ package org.ergoplatform.tools import org.ergoplatform.mining.difficulty.{DifficultyAdjustment, DifficultySerializer} import org.ergoplatform.modifiers.history.header.Header -import org.ergoplatform.nodeView.history.ErgoHistory.Difficulty -import org.ergoplatform.settings.ErgoSettings +import org.ergoplatform.nodeView.history.ErgoHistoryConstants.Difficulty +import org.ergoplatform.settings.ErgoSettingsReader import org.ergoplatform.utils.generators.ErgoGenerators import scala.annotation.tailrec @@ -86,7 +86,7 @@ object DifficultyControlSimulator extends App with ErgoGenerators { def printTestnetData(): Unit = { val baseHeader = defaultHeaderGen.sample.get - val chainSettings = ErgoSettings.read().chainSettings.copy(epochLength = 1) + val chainSettings = ErgoSettingsReader.read().chainSettings.copy(epochLength = 1) val difficultyControl = new DifficultyAdjustment(chainSettings) val headers = Source.fromResource("difficulty.csv").getLines().toSeq.tail.map { line => diff --git a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala index 302ac4aac5..ff3227256a 100644 --- a/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala +++ b/src/test/scala/org/ergoplatform/utils/ErgoTestConstants.scala @@ -46,7 +46,7 @@ trait ErgoTestConstants extends ScorexLogging { Parameters(0, Parameters.DefaultParameters ++ extension, ErgoValidationSettingsUpdate.empty) } - val initSettings: ErgoSettings = ErgoSettings.read(Args(Some("src/test/resources/application.conf"), None)) + val initSettings: ErgoSettings = ErgoSettingsReader.read(Args(Some("src/test/resources/application.conf"), None)) implicit val settings: ErgoSettings = initSettings diff --git a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala index b38d920120..fc158d2f64 100644 --- a/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala +++ b/src/test/scala/org/ergoplatform/utils/HistoryTestHelpers.scala @@ -1,8 +1,9 @@ package org.ergoplatform.utils +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.history.ErgoHistory import org.ergoplatform.nodeView.history.storage.modifierprocessors.{EmptyBlockSectionProcessor, FullBlockPruningProcessor, ToDownloadProcessor} -import org.ergoplatform.nodeView.mempool.ErgoMemPool.SortingOption +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.SortingOption import org.ergoplatform.nodeView.state.StateType import org.ergoplatform.settings._ import org.scalacheck.Gen @@ -84,7 +85,7 @@ object HistoryTestHelpers { val ppM = ru.typeOf[ToDownloadProcessor].member(ru.TermName("pruningProcessor")).asMethod val pp = procInstance.reflectMethod(ppM).apply().asInstanceOf[FullBlockPruningProcessor] val f = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("minimalFullBlockHeightVar")).asTerm.accessed.asTerm - runtimeMirror.reflect(pp).reflectField(f).set(ErgoHistory.GenesisHeight) + runtimeMirror.reflect(pp).reflectField(f).set(GenesisHeight) val f2 = ru.typeOf[FullBlockPruningProcessor].member(ru.TermName("isHeadersChainSyncedVar")).asTerm.accessed.asTerm runtimeMirror.reflect(pp).reflectField(f2).set(true) } diff --git a/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala b/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala index 8df386a697..3b708d9d06 100644 --- a/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala +++ b/src/test/scala/org/ergoplatform/utils/NodeViewTestConfig.scala @@ -2,7 +2,7 @@ package org.ergoplatform.utils import org.ergoplatform.mining.DefaultFakePowScheme import org.ergoplatform.nodeView.state.StateType -import org.ergoplatform.settings.{ErgoSettings, NipopowSettings} +import org.ergoplatform.settings.{ErgoSettings, ErgoSettingsReader, NipopowSettings} case class NodeViewTestConfig(stateType: StateType, @@ -10,7 +10,7 @@ case class NodeViewTestConfig(stateType: StateType, popowBootstrap: Boolean) { def toSettings: ErgoSettings = { - val defaultSettings = ErgoSettings.read() + val defaultSettings = ErgoSettingsReader.read() defaultSettings.copy( chainSettings = defaultSettings.chainSettings.copy( powScheme = new DefaultFakePowScheme(defaultSettings.chainSettings.powScheme.k, defaultSettings.chainSettings.powScheme.n) diff --git a/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala b/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala index d78b852d81..aeb8fcbf71 100644 --- a/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala +++ b/src/test/scala/org/ergoplatform/utils/NodeViewTestOps.scala @@ -11,8 +11,9 @@ import org.ergoplatform.nodeView.history.ErgoHistory import org.ergoplatform.nodeView.state.{ErgoState, StateType, UtxoState} import org.ergoplatform.settings.Algos import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ +import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._ +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier.LocallyGeneratedModifier import scorex.core.validation.MalformedModifierError import scorex.util.ModifierId diff --git a/src/test/scala/org/ergoplatform/utils/Stubs.scala b/src/test/scala/org/ergoplatform/utils/Stubs.scala index 556dd034ca..2369d16c2d 100644 --- a/src/test/scala/org/ergoplatform/utils/Stubs.scala +++ b/src/test/scala/org/ergoplatform/utils/Stubs.scala @@ -11,13 +11,13 @@ import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnconfirmedTransaction} import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.LocallyGeneratedTransaction import org.ergoplatform.nodeView.ErgoReadersHolder.{GetDataFromHistory, GetReaders, Readers} -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.{ErgoHistory, ErgoHistoryConstants} import org.ergoplatform.nodeView.mempool.ErgoMemPool -import org.ergoplatform.nodeView.mempool.ErgoMemPool.{ProcessingOutcome, SortingOption} +import org.ergoplatform.nodeView.mempool.ErgoMemPoolTypes.{ProcessingOutcome, SortingOption} import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.nodeView.state.{DigestState, ErgoStateContext, StateType} -import org.ergoplatform.nodeView.wallet.ErgoWalletActor._ -import org.ergoplatform.nodeView.wallet.ErgoWalletService.DeriveNextKeyResult +import org.ergoplatform.nodeView.wallet.ErgoWalletActorMessages._ +import org.ergoplatform.nodeView.wallet.ErgoWalletServiceUtils.DeriveNextKeyResult import org.ergoplatform.nodeView.wallet._ import org.ergoplatform.nodeView.wallet.persistence.WalletDigest import org.ergoplatform.nodeView.wallet.scanning.Scan @@ -182,7 +182,7 @@ trait Stubs extends ErgoGenerators with ErgoTestHelpers with ChainGenerator with case RescanWallet(_) => sender ! Success(()) - case GetWalletStatus => sender() ! WalletStatus(true, true, None, ErgoHistory.GenesisHeight, error = None) + case GetWalletStatus => sender() ! WalletStatus(true, true, None, ErgoHistoryConstants.GenesisHeight, error = None) case _: CheckSeed => sender() ! true diff --git a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala index 42407311f2..6c9bf3bf4b 100644 --- a/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala +++ b/src/test/scala/org/ergoplatform/utils/WalletTestOps.scala @@ -5,7 +5,7 @@ import org.ergoplatform._ import org.ergoplatform.mining.CandidateGenerator import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.mempool.ErgoTransaction -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.{ErgoState, UtxoState} import org.ergoplatform.nodeView.wallet.ErgoWallet import org.ergoplatform.nodeView.wallet.IdUtils._ @@ -86,7 +86,7 @@ trait WalletTestOps extends NodeViewBaseOps { } CandidateGenerator.collectRewards(Some(genesisEmissionBox), - ErgoHistory.EmptyHistoryHeight, + EmptyHistoryHeight, Seq.empty, publicKey, emptyStateContext, @@ -97,7 +97,7 @@ trait WalletTestOps extends NodeViewBaseOps { val inputs = IndexedSeq(new Input(genesisEmissionBox.id, emptyProverResult)) val assets: Seq[(TokenId, Long)] = replaceNewAssetStub(assetsIn, inputs) CandidateGenerator.collectRewards(Some(genesisEmissionBox), - ErgoHistory.EmptyHistoryHeight, + EmptyHistoryHeight, Seq.empty, publicKey, emptyStateContext, diff --git a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala index 1d210f38a0..f3cb4297ea 100644 --- a/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala +++ b/src/test/scala/org/ergoplatform/utils/generators/ErgoTransactionGenerators.scala @@ -5,7 +5,7 @@ import org.ergoplatform.modifiers.ErgoFullBlock import org.ergoplatform.modifiers.history.BlockTransactions import org.ergoplatform.modifiers.history.header.Header import org.ergoplatform.modifiers.mempool.{ErgoTransaction, UnsignedErgoTransaction} -import org.ergoplatform.nodeView.history.ErgoHistory +import org.ergoplatform.nodeView.history.ErgoHistoryConstants._ import org.ergoplatform.nodeView.state.wrapped.WrappedUtxoState import org.ergoplatform.nodeView.state.{BoxHolder, ErgoStateContext, VotingData} import org.ergoplatform.nodeView.wallet.requests.{ExternalSecret, TransactionSigningRequest} @@ -61,7 +61,7 @@ trait ErgoTransactionGenerators extends ErgoGenerators with Generators { def ergoBoxGenForTokens(tokens: Seq[(TokenId, Long)], propositionGen: Gen[ErgoTree]): Gen[ErgoBox] = { - ergoBoxGen(propGen = propositionGen, tokensGen = Gen.oneOf(tokens, tokens), heightGen = ErgoHistory.EmptyHistoryHeight) + ergoBoxGen(propGen = propositionGen, tokensGen = Gen.oneOf(tokens, tokens), heightGen = EmptyHistoryHeight) } def unspendableErgoBoxGen(minValue: Long = parameters.minValuePerByte * 200, diff --git a/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala b/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala index 775b58d8d0..6d1553c561 100644 --- a/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala +++ b/src/test/scala/scorex/testkit/properties/NodeViewHolderTests.scala @@ -7,8 +7,9 @@ import org.ergoplatform.nodeView.history.ErgoHistory import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec import org.ergoplatform.nodeView.ErgoNodeViewHolder.CurrentView -import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.{GetDataFromCurrentView, LocallyGeneratedModifier} -import org.ergoplatform.network.ErgoNodeViewSynchronizer.ReceivableMessages._ +import org.ergoplatform.nodeView.ErgoNodeViewHolder.ReceivableMessages.GetDataFromCurrentView +import org.ergoplatform.network.ErgoNodeViewSynchronizerMessages._ +import org.ergoplatform.nodeView.ErgoNodeViewHolderLocallyGeneratedModifier.LocallyGeneratedModifier import org.ergoplatform.nodeView.state.ErgoState import scorex.testkit.generators._ import scorex.testkit.utils.AkkaFixture