rippled
ValidatorSite_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright 2016 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/misc/ValidatorSite.h>
21 #include <ripple/basics/Slice.h>
22 #include <ripple/basics/base64.h>
23 #include <ripple/basics/strHex.h>
24 #include <ripple/protocol/HashPrefix.h>
25 #include <ripple/protocol/PublicKey.h>
26 #include <ripple/protocol/SecretKey.h>
27 #include <ripple/protocol/Sign.h>
28 #include <ripple/protocol/digest.h>
29 #include <ripple/protocol/jss.h>
30 #include <boost/algorithm/string/join.hpp>
31 #include <boost/algorithm/string/predicate.hpp>
32 #include <boost/asio.hpp>
33 #include <boost/range/adaptor/transformed.hpp>
34 #include <chrono>
35 #include <date/date.h>
36 #include <test/jtx.h>
37 #include <test/jtx/TrustedPublisherServer.h>
38 #include <test/unit_test/FileDirGuard.h>
39 
40 namespace ripple {
41 namespace test {
42 namespace detail {
43 constexpr const char*
45 {
46  return R"vl({
47  "public_key": "ED2677ABFFD1B33AC6FBC3062B71F1E8397C1505E1C42C64D11AD1B28FF73F4734",
48  "manifest": "JAAAAAFxIe0md6v/0bM6xvvDBitx8eg5fBUF4cQsZNEa0bKP9z9HNHMh7V0AnEi5D4odY9X2sx+cY8B3OHNjJvMhARRPtTHmWnAhdkDFcg53dAQS1WDMQDLIs2wwwHpScrUnjp1iZwwTXVXXsaRxLztycioto3JgImGdukXubbrjeqCNU02f7Y/+6w0BcBJA3M0EOU+39hmB8vwfgernXZIDQ1+o0dnuXjX73oDLgsacwXzLBVOdBpSAsJwYD+nW8YaSacOHEsWaPlof05EsAg==",
49  "blob" : "eyJzZXF1ZW5jZSI6MzcsImV4cGlyYXRpb24iOjU5NDE3MjgwMCwidmFsaWRhdG9ycyI6W3sidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ0OUY4RUI4MDcxRTI2RDRFMDY3MjM4RDYyRDY3Q0E2RUJGQjI5OEI0QTcyRENGQUQ1MzZBN0VDODkyNUM1MTlCIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMUorT3VBY2VKdFRnWnlPTll0WjhwdXY3S1l0S2N0ejYxVGFuN0lrbHhSbTNNaEFvZ01tUVRSQUZLLyttL1hXUWZKdlhUZU1jYWl5RjZna2hnQXNzZExPY2lJZGtZd1JBSWdOeFlhdkpQeUhBTnV4b2dRWTdSTkJQOXRab2daSnhGMXdacXptNGEzN0dnQ0lCT3ZiZVE4K1A0NkNDSWN5NFpDWkE1clpaKzkzSDBhS0paUTMrSUEwT091Y0JKQUFTVHBRS3RFSmtlcXdIeitqS1dOdldsMHNIUlFaU1NKdVlpTXl5VWE3eXRwc2V2Nk5Hb0ZuMWJOcFlUZ3ZzYVB4b3o3dkhza0RoMlo2Z2ViU0RDUkNBPT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEODEwOEY3RDlFRTc3OURDMTA3NUVDM0NGOEVCOTAwNERERjg0Q0QwQTBGRjU3NzVDOUUzNzVDQ0FDREFBMzAyMiIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJCQ1BmWjduZWR3UWRldzgrT3VRQk4zNFROQ2cvMWQxeWVOMXpLemFvd0luTWhBbHZQSkFOUWNSVVNOVVIrTmxadW80a0dwWUY4bDlwSFBQMVpST09VY05ZUmRrWXdSQUlnUldaWnVKTEFmM1NOTUdvRnlnVWx1K2VBRDUxWm9IRk1jeW9pY24wV0t1Y0NJR3c0bjljVkRQT0JHQzh3bEpEeTkyODJ4OVJkT3dvMWNvMmcrTlpsYy9ETmNCSkFLSmhLL2FtNkw3S0U0NTBOVnpocFZWb0w4T0ZNbzBtRnhrOEJERzZRTzJjU05NTjNPeXdmNDBEK0lsZXM5TFh4eHZ2UEI2Z1dTbVBsd0Y3ZE5SOUdBUT09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDdFM0JBRkY5MDFERTUyNUIwMEIyQzFGRTE5QUY0NDlBMDgwQjVGMzEwMEM2RUMxODJDODY3QUY2MUY3MTBGRkQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxK082LzVBZDVTV3dDeXdmNFpyMFNhQ0F0Zk1RREc3QmdzaG5yMkgzRVAvWE1oQTUrR0RKaDJBcFdLQ2gyTjVvbXg0RkFPRkVxWE1qcXkxSEo1RTdXQTNGck9ka2N3UlFJaEFNUmV6d2pUQUwzNWpwamoxNWpxb0hVdlJtNys3aUhwVTQ3YUtFNkhFQ2haQWlCU01JWmFNV3Y2cU5KSG5pWXBzWUh4NE9QUHBCb0NNTWRNVkFHZkZpOWZLM0FTUUUwVFlpSXNHdjAveWxwcUdFQmlMa2syWGpyQTgrK0FrenByOXZjVHRya0hpRERvMGNIS085bVJVTEFYZXNSck95RmI1UWNPMGwwVnN3ZXZENWpsc3drPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ0NUU4MEEwNEQ3OUNCOURGMDBBRUJEODZEQ0RDMTY4NkQ2NDE5RUE5RTVFMEU3MUYxQTgxN0UwOEI1MDc2QTU1IiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMUY2QW9FMTV5NTN3Q3V2WWJjM0JhRzFrR2VxZVhnNXg4YWdYNEl0UWRxVlhNaEF4Wm8xNTdwY0I5ZGU2U21rN2hvSzN3TkNBcjRhRlp0ZkFQaTdDRTRtTkpsZGtjd1JRSWhBTGxWalhDZml5L210WEJXc050Nzd0NGpLY05FQnBSVjh6ditTcFU1bENoMEFpQmE4dm84eHhwdmlZbGY0emRHK25RaEIyT2dma1FaWlBNSE90N0NhWHpYZ1hBU1FMOE81cDA4M21nNEtLTDh1WmZNYVVxZGd6dUowR3RhMWx5VVdQY3RUUEN4WTEzNVh3SytuSkFkRnNJVUZOSjlNUGpucENtU2pZVnpWYTZNNS9uQWNBST0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERDhDODg2NDI3OTVDRTY5QzVCNzgwRTAxNzAyQzM3MEY5NTA3RDBCNjQ0MzNGMTdFRkU3MEYyNjM3QTQwQURCNyIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTNZeUlaQ2VWem1uRnQ0RGdGd0xEY1BsUWZRdGtRejhYNytjUEpqZWtDdHQzTWhBbkZmcityOUJYZHNYRS9jQmxKTXlkL1hzTzFBNVhFWUNjdHJzdkxFWCtEbWRrY3dSUUloQU5SY1JNZzlTQVhvYU92SERaMmF2OVJ6RWFaYVZFTmZRaVZnc2krT3gzRjBBaUIyc25TSU9tNmM0L2luYnRVMFVtV0xRVHp1d2tPZFVGUElCOEF4OGRtR3VIQVNRTVVJZlhNajk2a2NGVFNKbk1GQy9tVy9BUThiS1hrRnJyazBDVVRGRkt3ZUVqVHErU1RyRmk2cUxMMk1UN252ZUd4c1hCQ2d6dGpjMHFHYXM5S0ZXZ009In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREJERUI5MDFGN0M3NUQwRTIwQzZDNDJBRjAzQkUwREE0MDM3N0FGMTkzOUExOEIzQ0IzNjc5NjYxREQ1RjlGNzQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUyOTY1QWZmSFhRNGd4c1FxOER2ZzJrQTNldkdUbWhpenl6WjVaaDNWK2ZkSE1oQWczY3lLTlBNUHFLZ1I3a0lpN2MvOEdML1lnZEJ0ZzRtU0FXdndtYWV2Vkdka1l3UkFJZ1d6RzhHcVlnM1lwd0RzOHhYYTlYcUxIc3M3NktUMnVBSFJoVVhGVlVxQ1FDSUcyRXZiRktueGV6UmQ5Y3BQSFN0MzJIWEsrUDQrYUwzcDIrdnFsQ3hSUjljQkpBYm9YVG1ZVGF5b2NBM3pmOWRXRVh0eWFlT0dDMWs1V2RZVVJ6UGxlZXZ2YWxSNHhWb1h6czM4aUdQeEZyL3BBOW5MK000ZHV1MEdLQ0hsVmlyK2ZCQWc9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURBMTc4NzFFNzJCMEM1NzBBQzQzNDVDNjBDRjAyQUZCQkI3NDBBNjMxQjdBRDBFMUU1NzMyMTY1NzREOUFFQTAyIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMmhlSEhuS3d4WENzUTBYR0RQQXErN3QwQ21NYmV0RGg1WE1oWlhUWnJxQW5NaEFvanl1emd0cmVRa3hRajhwckh4T3NiRGNGNWZ1NFhYYjBLeEVML1BxNUhoZGtjd1JRSWhBTmZQRExaUDQ3YUNXd3Q1a0JucDc1QnV1Q2dwOWM0QmZKUGQ2NlNGQ3c2MUFpQUp2ZWdCdnZQSXJlYytYT1N6S1JmaTV1dVhXeHRsOUV5cjJhUEJZWHZiUkhBU1FNVUxZRW83YmVSZm9VQ25qazFzVFl5WTkxdExJR0xnbm5hV1hoVW04MCt6czVJR2VnazhxaWpLQXRCT011QkM3MWxBQjRLaEpjK2RCMnJwTU9GYzVndz0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERjQ2RUUyN0FEMEUxQTcxNEFGRUNEQTgxNkVBQjcxMTQ2MTRGQ0I5MkQwQ0I0RDk3QjZBODhFRDQzNDM0QUZDOSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTMwYnVKNjBPR25GSy9zMm9GdXEzRVVZVS9Ma3RETFRaZTJxSTdVTkRTdnlYTWhBdzBBVFdqVlR0NEZmZUtPN2t2NmZGZ2QvZ28yK2Q1QlN5VWNVUm1SV25UdGRrY3dSUUloQU13T2dEZWM3UVlZTm5nc3BnOTB3RXZWYnNvaDJ1eDE0UlBUdytHSGFYTmxBaUFMZ2ZFc3orQUY0ZXlYL1k1aTQ0VnJGakZGSU1XVWZPWmFRSnRzeHRlTTFYQVNRTE9hRjB0MlpwcVZLZDhKRVNRVlkrelU1NjdpQUFHMmFtVFBaeDk1ODc1UzlBNlBsK2tINVRHSE1BZVdqZ1dTcWZoM20ySEJKWDdOSWNYYjk4dnk5QUE9In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDZFNEM0MUU1OUZGQkVCNTE3MjZFNTQ0Njg1MDJGRTY0MzcyMzhGQTc4RUE1MTYzNEU3QkYwRDA5MTcxQUVFOEYiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxdVRFSGxuL3ZyVVhKdVZFYUZBdjVrTnlPUHA0NmxGalRudncwSkZ4cnVqM01oQXV6dEdXYi9PaTEvVjVtNWR1aldyOUhtYktSeUs0WFlrK2ttdUZQU2dBRnJka1l3UkFJZ2ZRK0JnWFg2UWJsWnk0SDA1bzdHUFNJd3FTN1FRUlVXN2RxRjU0SUFpaU1DSUg0WGZMdzk1NmlFYW94Wk9rN0tjdGluMlg5aE1mYUxON3d5czl5QVVGb1pjQkpBdWVFaTg0WFIzTGwxR0xKV2FuVzFnMU1kVWovMFBBeEpidzZFRVFSdUczemRudVJITlhsZDZVWkFiSWtWY1AwenRmcXVsQnpqYmNzTERPS0ZFaWNTQmc9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCNkZDOEU4MDNFRThFREMyNzkzRjFFQzkxN0IyRUU0MUQzNTI1NTYxOERFQjkxRDNGOUIxRkM4OUI3NUQ0NTM5IiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMjIvSTZBUHVqdHduay9Ic2tYc3U1QjAxSlZZWTNya2RQNXNmeUp0MTFGT1hNaEE4VmR2SEZ5U2NCeVFHVFlOR2VPdkIwKzY3Z1dhcWVmY2Z2Ums1K0t3Z1YxZGtZd1JBSWdaRnVsTy9BaU1vY3puZzZpLzRCa2Z6VDdqOWx4RjRQUDF1ZmdyT1FhSjhzQ0lCWC9FOFpicG43dFdxZ0F5TnlXcFZQa2hGbWFVTXFFcnk4V29VVDFmZEdRY0JKQXY1MVJxSnhnZy9Wcm5yWndpTEsyRGMwQ0tiaUxQTzVISjRaTXNqZFBUMmdSYzk3cldrQVh1VjJMNlBORk81OXh5dW9hWm1TTWxaWXZxU0dQcGZGN0J3PT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVENjkxMzAzOTkyRkVDNjRFNkJDNEJBQ0QzNkFFNkU1QUVEQzIzRjI4NjFCNkQ4RUZCOUZENzdFRTNFQURFMzQzNSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTFwRXdPWkwreGs1cnhMck5OcTV1V3UzQ1B5aGh0dGp2dWYxMzdqNnQ0ME5YTWhBaTJBWEpRZ28vSnVXM3I3Zi82Q2NWc0dOMVltSWoxMUdpSUVTSEJuUVNrOGRrY3dSUUloQU5DREVReW1yZDZ2ZVQzb3VhY0Y2ZmhCcjV3THczR21YZzFyTUNMVnZCelpBaUE4dVdRK3RxZDQ2V21mQmV4alNCUTJKZDZVQUdkckh2amNDUTJaZ1Nvb0NuQVNRRmtIbCtENy9VM1dCeVlQMzg0K3BjRkRmMkdpNFdJUkhWVG81OGNxZGs1Q0Rpd2MxVDByRG9MaG1vNDFhM2YrZHNmdGZ3UjRhTW13RmNQWExucmpyQUk9In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREFEMTY2NjdGMDE4NUREQkI3RkE2NUIyMkY0QjdEMzEwQkY1QzNFMkQ5QjgyM0ZCMDZBM0E0MUFGOEFDODNCQzEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUydEZtWi9BWVhkdTMrbVd5TDB0OU1RdjF3K0xadUNQN0JxT2tHdmlzZzd3WE1oQXF3ZUUzUElTM0U0NEtoTXFLakt0YmtCZThIOEdiaXVvQVhBWURSb1ZSSG9ka1l3UkFJZ2FnR2tYdG93VXliZGx0S29qdjBsdnZmbHJsUTlJUm5QT2pla0Y2MGlIemdDSUNnNlpvY0lNemtVdXZPOTFCRW9ybUlXbVg0Ry9NR1QyenJvNkkvUHZCOFhjQkpBY0pMWGt0L3cva2N3RXZOaVptaTJpMm5NbjF3aVAzTFM5TkpqQlBqdThLRkxBTWcwTzl5ZFFUNjdVL0FMWU9lVFBUTzIvaTJZdzlPU2xpYnRxaGd6REE9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURDMjQ1MDI3QTUyRUU1MzE4MDk1NTk4RUMzQUI2NUZGNEEzQjlGOTQyOEUxMEIyRjNDNkYzOURFMTVBMTVDOTBBIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllM0NSUUo2VXU1VEdBbFZtT3c2dGwvMG83bjVRbzRRc3ZQRzg1M2hXaFhKQ25NaEEvOC85cktVZEE2MWovZklFUC9jcUxweEJsbUloUDJyZzFkN05hRVB5S1YrZGtjd1JRSWhBSXhFME0vRko1MHZmWlc2ZlBweTR5Q1p1bVk5bjBvYnJPb2pVa2ptNTVhMEFpQmo1Nk8wTXBvcEdvWTlIeEMvKzR3Tk8zNkhvN0U5Q1FlSHNuS3JlRGRzQVhBU1FJWVVkODFqYmlWVWxFVDRkR29HMnArY2YrMkdxRVhYNWZKTVNTeVgvcWUwWGZSNGNPKzRxbGdtak1RZENSREJXQUJIVnZkTi95WnlpL3JMMmMrV3JRYz0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVENDI0NkFBM0FFOUQyOTg2Mzk0NDgwMENDQTkxODI5RTQ0NDc0OThBMjBDRDlDMzk3M0E2QjU5MzQ2Qzc1QUI5NSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTFDUnFvNjZkS1lZNVJJQU15cEdDbmtSSFNZb2d6Wnc1YzZhMWswYkhXcmxYTWhBa20xbHowYzhRWFdmSjliMXZCNzJkTGFidzh3WUlkOE10bnBzSEhCRUM4cGRrWXdSQUlnUWxiNkhKNTNoc1RBZlZpZCtBT2RCVnZNRjdyYWhJS05MQkhVZ241MnpCRUNJR0xVcUZ1OGExQUFIUkpjVm9uS1lFbm1oSndiQ1hMbitqZTduYTFXRDEvb2NCSkFFNHZmdnJHU21aQzJ1QVVHbU01ZElCdG9TZ0VVZXkrMlZsZURZRXNjZTk0dHhZY2pSOFo3UUxOYWxpRDh3L2JENS9odllROG1lVjFXZzFqSkZOZTBDQT09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDJDMTQ2OEI0QTExRDI4MUY5M0VGMzM3Qzk1RTRBMDhERjAwMDBGREVGQjZEMEVBOUJDMDVGQkQ1RDYxQTFGNUEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUwc0ZHaTBvUjBvSDVQdk0zeVY1S0NOOEFBUDN2dHREcW04QmZ2VjFob2ZXbk1oQWtNVW1DRDJhUG1nRkREUm1pbXZTaWNTSVNjdzZZTnI0MkR3NFJBZHdyT0Fka2N3UlFJaEFKRk9ITWc2cVRHOHY2MGRocmVuWVlrNmN3T2FSWHEwUk5tTGp5eUNpejVsQWlBZFUwWWtEVUpRaG5OOFJ5OHMrNnpUSkxpTkxidE04b08vY0xudXJWcFJNM0FTUUdBTGFySEFzSmtTWlF0R2RNMkFhUi9qb0ZLL2poRFU1NytsK1JTWWpyaS95ZEUyMERhS2Fud2tNRW9WbEJUZzdsWDRoWWpFbm1rcW83M3dJdGhMT0FRPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURBNTRDODVGOTEyMTlGRDI1OTEzNEI2QjEyNkFENjRBRTcyMDRCODFERDQwNTI1MTA2NTdFMUE1Njk3MjQ2QUQyIiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMmxUSVg1RWhuOUpaRTB0ckVtcldTdWNnUzRIZFFGSlJCbGZocFdseVJxMG5NaEFsOGNKZXJQdit2bzFCSzYxMXhWVHBHeGpqci9DdXhQVGdVOFVSTTRlVFo1ZGtZd1JBSWdkSzNjUVYyWS92aVpuZS9QYm9LU0tld25nVHVJTjJNNmM4YXp3cWMyMHVVQ0lBYzZHb05UK1AyWUJ5NDlnZGF1NFA3eVN3V29RWDVuZjlkUXhpUWF2NXdJY0JKQXFpQ0swZDZRUlpTcGlWSHA4TzlubEtYQ1NFaHNpU05jV2NFRm0vZkdoSkFuQU4wT3Y5SElOSWQxcHhyQm4yZEtSZWdMVHZZRzNCcGJ6Ly9ITGdFZERBPT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEOUFFNEY1ODg3QkEwMjlFQjdDMDg4NDQ4NkQyM0NGMjgxOTc1Rjc3M0Y0NEJEMjEzMDU0MjE5ODgyQzQxMUNDNyIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJhNVBXSWU2QXA2M3dJaEVodEk4OG9HWFgzYy9STDBoTUZRaG1JTEVFY3gzTWhBbUcyemd2OEZCWnNaSlU4YVBhcHdvOWNJcVF2NC9NU1Mxb1ZBNWVWTWl3TGRrWXdSQUlnRitMT2U0ZVkwZ3A5dHRxaDJnbnYrejc1T3FMeU9RTXBHUEFMZ20rTnRPc0NJQ0RYQlpWUHRwcm1CRGtCSmtQRlNuRTU1RDllS1lSSDh6L2lZMUV0cE5wbGNCSkFBREVXR1ZUODBPd2hkMWxoMkpzVS9vWmxtZU5GNVdON1l2bEI4bGxFeGFSS0VWQytHVzlXZytpTklRM3JtVjdQOGFOYVZ1YWFiRzAwZk9na2d6TmhEdz09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFREE4RDI5RjQwQ0VCMjg5OTU2MTc2NDFBM0JDNDI2OTJFMURFODgzMjE0RjYxMkZCQjYyMDg3QTE0OEU1RjZGOUEiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUybzBwOUF6cktKbFdGMlFhTzhRbWt1SGVpRElVOWhMN3RpQ0hvVWpsOXZtbk1oQW5ZblA3RWc2VmdObkVVVFJFMjlkNjRqUVQvaUJjV1RRdE5yVXp5RDZNSitka2N3UlFJaEFPRXNWNWFuVGtsb1NtVFpSYmltTXlCS3FIb0pZWGNCQmU4bExpUFlDN21VQWlBejJhTk9wZlEvMUx5Y1dsb0lNdmRoeHppbnE1WDdVYXMvdU9TYjl3aDhkM0FTUUxWa2ZwVy9HTzZ3ZFQ2QXV1U0o1NlR0TTM0M3BETkgraVN6eGx0SWZkclBpVXhUNXJmNGsyMWxRUXVQQ2xYbTkrU2ZLckNpVVhaSzdkajAvR1dUWVFnPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQzOEIwMjg4RUEyNDBCNENERUMxOEExQTYyODlFQjQ5MDA3RTRFQkMwREU5NDQ4MDNFQjdFRjE0MUM1NjY0MDczIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMDRzQ2lPb2tDMHpld1lvYVlvbnJTUUIrVHJ3TjZVU0FQcmZ2RkJ4V1pBYzNNaEFnT0tjdkl1Y2hhbHJady9nbFR1T3hWM0lPQ2Nwb3J4TUI3SnFBVnVwazFlZGtjd1JRSWhBT3ZSenBlK0lZWksxTXlJbklRWjg3SnZQMko4U0lYQ1haTVBCQ2RJVEJhbUFpQVNhdkpYaTlwd3M4ckRESlN4aEdNbG1FN3pJNWJTQThpdnRSQzlMZ3ErVVhBU1FEbDNlb3FMSUQrRVRKTk0remJNdXZ3dmNIRUl4ZUJaa1o5ZnA1akp2Nk9DVFB3bGo0VEpTdXkxYXZFV3FVWVMycml2NUR2bDJoYUZVb0NIZjR5YXdBQT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVERUUxMERDMzZBQ0Q5OTVDOEUwRTg2RTNDRDJGQkY4MzAxQTRBQzJCODg0N0I2MUExOTM1REU0OTczQjQwN0MwRSIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTN1RU53MnJObVZ5T0RvYmp6UysvZ3dHa3JDdUlSN1lhR1RYZVNYTzBCOERuTWhBbVgwdmI3aitsZ0JqRmpiTjlSbEE4Nko3QU8yVm42SExxdU8zYWlzSzRtd2RrWXdSQUlnZnhCTG43aTRqZy9kaTBVMjVxNmtJYlZmVHpxYkEwU0NwUTBJNTdUT0ZrY0NJRk10SlFwRU5qQjJLMkVtdkJIUHZOY3d1U1BjM3ZzRWVxRTJyTkovY1Q1RGNCSkFmNjhYUEZ1NVJqQ2VMZ3BGSk03UEtGTGdvVjhlMW54TzVld2pxOVErVEFFR25GeVMwSU93ZjZwT090SVZNZFZlWHUxdjZwNGZoWFFrZGloSHQxeDZBZz09In0seyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDU4M0VDRDA2QzNCNzM2OTk4MEU2NUM3OEM0NDBBNTI5MzAwRjU1N0VEODEyNTYyODNGN0RENUFBMzUxM0EzMzQiLCJtYW5pZmVzdCI6IkpBQUFBQUZ4SWUxWVBzMEd3N2MybVlEbVhIakVRS1VwTUE5VmZ0Z1NWaWcvZmRXcU5ST2pOSE1oQXl1VW56WloxbjIvR2FUbUUxbTdIL3Y5WWxaeURFd0hZM2dTSFVBM0lDTDlka1l3UkFJZ0h4MlBIdmlkb04rNXlHOVdlQVMyazdud0lNOGFqeFFXNndqdnQ4a0JlbkFDSUROeFFQUWtEeURKSDlzZVM1QzYybUFhclFtZ2lOODlZUzNqaE50bnZFSXFjQkpBajdKaDBLYWMrYUpkcG9lcHUvK2VKS25uRlE3WUJ5WkI4ZU1aK1NTMXpMaEUrbGlwLzQ5cXFWTmNwQXhFcWZhR3R4SnpvREREMS9RYnVVN05PU1BrQ2c9PSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQ5NUM1MTcyQjJBRDdEMzk0MzRFRUJDNDM2QjY1QjNCQjdFNThENUMxQ0VGQzgyMEI2OTcyQUNBRDc3NkUyODZBIiwibWFuaWZlc3QiOiJKQUFBQUFGeEllMlZ4UmNyS3RmVGxEVHV2RU5yWmJPN2ZsalZ3Yzc4Z2d0cGNxeXRkMjRvYW5NaEFpcWNSZGUzTVFaMDc1ZmE0Wk5OeVJhWUpHTWRCTmtCbm4zYlFyS3NlQkRRZGtZd1JBSWdVK0xmY0U3MURQVnJPK0t0VUJqUTlEMnUway9QcjdsdWtPMW5QUmo2aFNBQ0lETkxZQy9KRmdvYkNzSWEwQkd3KzZiVW5PdzltZVUzRmRYZ1I3UTdTb3FKY0JKQVhRYWtPb1FuUHAzcGNMTDd6ZEtDUFVYNGIrL0ZDOVVuaHFwK085eFFGblJhQ1dWR21rNU1KT0lNczRXT1FkcE0xajNPZ1NzQUJtUnVDWFl2d28vbkR3PT0ifSx7InZhbGlkYXRpb25fcHVibGljX2tleSI6IkVEOTAxNjNEMkJGMEI3Nzg4OTA0QzRBNDExOEQ3RDk2ODkyMEU4NDdEODhCNzkxNzgzOTA4MzdERTNDQTI2MTU2MiIsIm1hbmlmZXN0IjoiSkFBQUFBRnhJZTJRRmowcjhMZDRpUVRFcEJHTmZaYUpJT2hIMkl0NUY0T1FnMzNqeWlZVlluTWhBNzJWVFJpR2hrSkJ0cWdHSER6SGo3WWJDNitOc0VLckZITnVFL0xPM1RuNWRrWXdSQUlnZjhzK2ZZdDBsbHJLUTJxaVdQbkdtYjZxSlBvZThPbkNNM1ZTMjlYS2JZWUNJSEdubEo0T1RzMmRYdWdPNkJ0bzYzTnBEdnZxSitXSXdkWUtxWjZCaUJmemNCSkFHdk50a29nNHBmRTVkWlJ3bWljODdaQmVldW5PaDRZcEwwU0VSZHhXajQzQ3M5ODE1ekZKdVp5c1NhVVgyUi92ZEUyVktxdlNncXF0REVuck1vMm9Bdz09In1dfQ==",
50  "signature" : "9FF30EDC4DED7ABCD0D36389B7C716EED4B5E4F043902853534EBAC7BE966BB3813D5CF25E4DADA5E657CCF019FFD11847FD3CC44B5559A6FCEEE4C3DCFF8D0E",
51  "version": 1
52 }
53 )vl";
54 }
55 
56 auto constexpr default_expires = std::chrono::seconds{3600};
58 } // namespace detail
59 
60 class ValidatorSite_test : public beast::unit_test::suite
61 {
62 private:
64 
65  void
67  {
68  testcase("Config Load");
69 
70  using namespace jtx;
71 
72  Env env(*this, envconfig(), nullptr, beast::severities::kDisabled);
73  auto trustedSites =
74  std::make_unique<ValidatorSite>(env.app(), env.journal);
75 
76  // load should accept empty sites list
77  std::vector<std::string> emptyCfgSites;
78  BEAST_EXPECT(trustedSites->load(emptyCfgSites));
79 
80  // load should accept valid validator site uris
81  std::vector<std::string> cfgSites({
82  "http://ripple.com/", "http://ripple.com/validators",
83  "http://ripple.com:8080/validators",
84  "http://207.261.33.37/validators",
85  "http://207.261.33.37:8080/validators",
86  "https://ripple.com/validators",
87  "https://ripple.com:443/validators",
88  "file:///etc/opt/ripple/validators.txt",
89  "file:///C:/Lib/validators.txt"
90 #if !_MSC_VER
91  ,
92  "file:///"
93 #endif
94  });
95  BEAST_EXPECT(trustedSites->load(cfgSites));
96 
97  // load should reject validator site uris with invalid schemes
98  std::vector<std::string> badSites({"ftp://ripple.com/validators"});
99  BEAST_EXPECT(!trustedSites->load(badSites));
100 
101  badSites[0] = "wss://ripple.com/validators";
102  BEAST_EXPECT(!trustedSites->load(badSites));
103 
104  badSites[0] = "ripple.com/validators";
105  BEAST_EXPECT(!trustedSites->load(badSites));
106 
107  // Host names are not supported for file URLs
108  badSites[0] = "file://ripple.com/vl.txt";
109  BEAST_EXPECT(!trustedSites->load(badSites));
110 
111  // Even local host names are not supported for file URLs
112  badSites[0] = "file://localhost/home/user/vl.txt";
113  BEAST_EXPECT(!trustedSites->load(badSites));
114 
115  // Nor IP addresses
116  badSites[0] = "file://127.0.0.1/home/user/vl.txt";
117  BEAST_EXPECT(!trustedSites->load(badSites));
118 
119  // File URL path can not be empty
120  badSites[0] = "file://";
121  BEAST_EXPECT(!trustedSites->load(badSites));
122 
123 #if _MSC_VER // Windows paths strip off the leading /, leaving the path empty
124  // File URL path can not be a directory
125  // (/ is the only path we can reasonably assume is a directory)
126  badSites[0] = "file:///";
127  BEAST_EXPECT(!trustedSites->load(badSites));
128 #endif
129  }
130 
132  {
135  bool ssl;
136  bool failFetch = false;
137  bool failApply = false;
138  int serverVersion = 1;
143  };
144  void
146  detail::DirGuard const& good,
148  {
149  testcase << "Fetch list - "
150  << boost::algorithm::join(
151  paths |
152  boost::adaptors::transformed(
153  [](FetchListConfig const& cfg) {
154  return cfg.path +
155  (cfg.ssl ? " [https] v" : " [http] v") +
157  " " + cfg.msg;
158  }),
159  ", ");
160 
161  using namespace jtx;
162  using namespace std::chrono_literals;
163 
164  Env env(*this, [&]() {
165  auto p = test::jtx::envconfig();
166  p->legacy("database_path", good.subdir().string());
167  return p;
168  }());
169  auto& trustedKeys = env.app().validators();
170  env.timeKeeper().set(env.timeKeeper().now() + 30s);
171 
172  test::StreamSink sink;
173  beast::Journal journal{sink};
174 
175  PublicKey emptyLocalKey;
176  std::vector<std::string> emptyCfgKeys;
177  struct publisher
178  {
179  publisher(FetchListConfig const& c) : cfg{c}
180  {
181  }
184  std::string uri;
185  FetchListConfig const& cfg;
186  bool isRetry;
187  };
188  std::vector<publisher> servers;
189 
190  auto constexpr listSize = 20;
191  std::vector<std::string> cfgPublishers;
192 
193  for (auto const& cfg : paths)
194  {
195  servers.push_back(cfg);
196  auto& item = servers.back();
197  item.isRetry = cfg.path == "/bad-resource";
198  item.list.reserve(listSize);
199  while (item.list.size() < listSize)
200  item.list.push_back(TrustedPublisherServer::randomValidator());
201 
202  NetClock::time_point const expires =
203  env.timeKeeper().now() + cfg.expiresFromNow;
204  NetClock::time_point const effective2 =
205  expires - cfg.effectiveOverlap;
206  NetClock::time_point const expires2 =
207  effective2 + cfg.expiresFromNow;
208  item.server = make_TrustedPublisherServer(
209  env.app().getIOService(),
210  item.list,
211  expires,
212  {{effective2, expires2}},
213  cfg.ssl,
214  cfg.serverVersion);
215  std::string pubHex = strHex(item.server->publisherPublic());
216  cfgPublishers.push_back(pubHex);
217 
218  if (item.cfg.failFetch)
219  {
220  // Create a cache file
221  auto const name = good.subdir() / ("cache." + pubHex);
222  std::ofstream o(name.string());
223  o << "{}";
224  }
225 
226  std::stringstream uri;
227  uri << (cfg.ssl ? "https://" : "http://")
228  << item.server->local_endpoint() << cfg.path;
229  item.uri = uri.str();
230  }
231 
232  BEAST_EXPECT(
233  trustedKeys.load(emptyLocalKey, emptyCfgKeys, cfgPublishers));
234 
235  // Normally, tests will only need a fraction of this time,
236  // but sometimes DNS resolution takes an inordinate amount
237  // of time, so the test will just wait.
238  auto sites = std::make_unique<ValidatorSite>(env.app(), journal, 12s);
239 
241  for (auto const& u : servers)
242  uris.push_back(u.uri);
243  sites->load(uris);
244  sites->start();
245  sites->join();
246 
247  auto const jv = sites->getJson();
248  for (auto const& u : servers)
249  {
250  for (auto const& val : u.list)
251  {
252  BEAST_EXPECT(
253  trustedKeys.listed(val.masterPublic) != u.cfg.failApply);
254  BEAST_EXPECT(
255  trustedKeys.listed(val.signingPublic) != u.cfg.failApply);
256  }
257 
258  Json::Value myStatus;
259  for (auto const& vs : jv[jss::validator_sites])
260  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
261  myStatus = vs;
262  BEAST_EXPECTS(
263  myStatus[jss::last_refresh_message].asString().empty() !=
264  u.cfg.failFetch,
265  to_string(myStatus) + "\n" + sink.messages().str());
266 
267  if (!u.cfg.msg.empty())
268  {
269  BEAST_EXPECTS(
270  sink.messages().str().find(u.cfg.msg) != std::string::npos,
271  sink.messages().str());
272  }
273 
274  if (u.cfg.expectedRefreshMin)
275  {
276  BEAST_EXPECTS(
277  myStatus[jss::refresh_interval_min].asInt() ==
278  u.cfg.expectedRefreshMin,
279  to_string(myStatus));
280  }
281 
282  if (u.cfg.failFetch)
283  {
284  using namespace std::chrono;
285  std::stringstream nextRefreshStr{
286  myStatus[jss::next_refresh_time].asString()};
287  system_clock::time_point nextRefresh;
288  date::from_stream(nextRefreshStr, "%Y-%b-%d %T", nextRefresh);
289  BEAST_EXPECT(!nextRefreshStr.fail());
290  auto now = system_clock::now();
291  BEAST_EXPECTS(
292  nextRefresh <= now + (u.isRetry ? seconds{30} : minutes{5}),
293  "Now: " + to_string(now) + ", NR: " + nextRefreshStr.str());
294  }
295  }
296  }
297 
298  void
300  {
301  testcase << "File list - " << paths[0].first
302  << (paths.size() > 1 ? ", " + paths[1].first : "");
303 
304  using namespace jtx;
305 
306  Env env(*this);
307 
308  test::StreamSink sink;
309  beast::Journal journal{sink};
310 
311  struct publisher
312  {
313  std::string uri;
314  std::string expectMsg;
315  bool shouldFail;
316  };
317  std::vector<publisher> servers;
318 
319  for (auto const& cfg : paths)
320  {
321  servers.push_back({});
322  auto& item = servers.back();
323  item.shouldFail = !cfg.second.empty();
324  item.expectMsg = cfg.second;
325 
326  std::stringstream uri;
327  uri << "file://" << cfg.first;
328  item.uri = uri.str();
329  }
330 
331  auto sites = std::make_unique<ValidatorSite>(env.app(), journal);
332 
334  for (auto const& u : servers)
335  uris.push_back(u.uri);
336  sites->load(uris);
337  sites->start();
338  sites->join();
339 
340  for (auto const& u : servers)
341  {
342  auto const jv = sites->getJson();
343  Json::Value myStatus;
344  for (auto const& vs : jv[jss::validator_sites])
345  if (vs[jss::uri].asString().find(u.uri) != std::string::npos)
346  myStatus = vs;
347  BEAST_EXPECTS(
348  myStatus[jss::last_refresh_message].asString().empty() !=
349  u.shouldFail,
350  to_string(myStatus));
351  if (u.shouldFail)
352  {
353  BEAST_EXPECTS(
354  sink.messages().str().find(u.expectMsg) !=
355  std::string::npos,
356  sink.messages().str());
357  }
358  }
359  }
360 
361  void
363  {
364  auto fullPath = [](detail::FileDirGuard const& guard) {
365  auto absPath = absolute(guard.file()).string();
366  if (absPath.front() != '/')
367  absPath.insert(absPath.begin(), '/');
368  return absPath;
369  };
370  {
371  // Create a file with a real validator list
373  *this, "test_val", "vl.txt", detail::realValidatorContents());
374  // Create a file with arbitrary content
375  detail::FileDirGuard hello(
376  *this, "test_val", "helloworld.txt", "Hello, world!");
377  // Create a file with malformed Json
379  *this,
380  "test_val",
381  "json.txt",
382  R"json({ "version": 2, "extra" : "value" })json");
383  auto const goodPath = fullPath(good);
384  auto const helloPath = fullPath(hello);
385  auto const jsonPath = fullPath(json);
386  auto const missingPath = jsonPath + ".bad";
387  testFileList({
388  {goodPath, ""},
389  {helloPath,
390  "Unable to parse JSON response from file://" + helloPath},
391  {jsonPath,
392  "Missing fields in JSON response from file://" + jsonPath},
393  {missingPath, "Problem retrieving from file://" + missingPath},
394  });
395  }
396  }
397 
398 public:
399  void
400  run() override
401  {
402  testConfigLoad();
403 
404  detail::DirGuard good(*this, "test_fetch");
405  for (auto ssl : {true, false})
406  {
407  // fetch single site
408  testFetchList(good, {{"/validators", "", ssl}});
409  testFetchList(good, {{"/validators2", "", ssl}});
410  // fetch multiple sites
412  good, {{"/validators", "", ssl}, {"/validators", "", ssl}});
414  good, {{"/validators", "", ssl}, {"/validators2", "", ssl}});
416  good, {{"/validators2", "", ssl}, {"/validators", "", ssl}});
418  good, {{"/validators2", "", ssl}, {"/validators2", "", ssl}});
419  // fetch single site with single redirects
420  testFetchList(good, {{"/redirect_once/301", "", ssl}});
421  testFetchList(good, {{"/redirect_once/302", "", ssl}});
422  testFetchList(good, {{"/redirect_once/307", "", ssl}});
423  testFetchList(good, {{"/redirect_once/308", "", ssl}});
424  // one redirect, one not
426  good,
427  {{"/validators", "", ssl}, {"/redirect_once/302", "", ssl}});
429  good,
430  {{"/validators2", "", ssl}, {"/redirect_once/302", "", ssl}});
431  // UNLs with a "gap" between validUntil of one and validFrom of the
432  // next
434  good,
435  {{"/validators2",
436  "",
437  ssl,
438  false,
439  false,
440  1,
442  std::chrono::seconds{-90}}});
443  // fetch single site with undending redirect (fails to load)
445  good,
446  {{"/redirect_forever/301",
447  "Exceeded max redirects",
448  ssl,
449  true,
450  true}});
451  // two that redirect forever
453  good,
454  {{"/redirect_forever/307",
455  "Exceeded max redirects",
456  ssl,
457  true,
458  true},
459  {"/redirect_forever/308",
460  "Exceeded max redirects",
461  ssl,
462  true,
463  true}});
464  // one undending redirect, one not
466  good,
467  {{"/validators", "", ssl},
468  {"/redirect_forever/302",
469  "Exceeded max redirects",
470  ssl,
471  true,
472  true}});
473  // one undending redirect, one not
475  good,
476  {{"/validators2", "", ssl},
477  {"/redirect_forever/302",
478  "Exceeded max redirects",
479  ssl,
480  true,
481  true}});
482  // invalid redir Location
484  good,
485  {{"/redirect_to/ftp://invalid-url/302",
486  "Invalid redirect location",
487  ssl,
488  true,
489  true}});
491  good,
492  {{"/redirect_to/file://invalid-url/302",
493  "Invalid redirect location",
494  ssl,
495  true,
496  true}});
497  // invalid json
499  good,
500  {{"/validators/bad",
501  "Unable to parse JSON response",
502  ssl,
503  true,
504  true}});
506  good,
507  {{"/validators2/bad",
508  "Unable to parse JSON response",
509  ssl,
510  true,
511  true}});
512  // error status returned
514  good,
515  {{"/bad-resource", "returned bad status", ssl, true, true}});
516  // location field missing
518  good,
519  {{"/redirect_nolo/308",
520  "returned a redirect with no Location",
521  ssl,
522  true,
523  true}});
524  // json fields missing
526  good,
527  {{"/validators/missing",
528  "Missing fields in JSON response",
529  ssl,
530  true,
531  true}});
533  good,
534  {{"/validators2/missing",
535  "Missing fields in JSON response",
536  ssl,
537  true,
538  true}});
539  // timeout
541  good, {{"/sleep/13", "took too long", ssl, true, true}});
542  // bad manifest format using known versions
543  // * Retrieves a v1 formatted list claiming version 2
545  good, {{"/validators", "Missing fields", ssl, true, true, 2}});
546  // * Retrieves a v2 formatted list claiming version 1
548  good, {{"/validators2", "Missing fields", ssl, true, true, 0}});
549  // bad manifest version
550  // Because versions other than 1 are treated as v2, the v1
551  // list won't have the blobs_v2 fields, and thus will claim to have
552  // missing fields
554  good, {{"/validators", "Missing fields", ssl, true, true, 4}});
556  good,
557  {{"/validators2",
558  "1 unsupported version",
559  ssl,
560  false,
561  true,
562  4}});
563  using namespace std::chrono_literals;
564  // get expired validator list
566  good,
567  {{"/validators",
568  "Applied 1 expired validator list(s)",
569  ssl,
570  false,
571  false,
572  1,
573  0s}});
575  good,
576  {{"/validators2",
577  "Applied 1 expired validator list(s)",
578  ssl,
579  false,
580  false,
581  1,
582  0s,
583  -1s}});
584  // force an out-of-range validUntil value
586  good,
587  {{"/validators",
588  "1 invalid validator list(s)",
589  ssl,
590  false,
591  true,
592  1,
594  // force an out-of-range validUntil value on the future list
595  // The first list is accepted. The second fails. The parser
596  // returns the "best" result, so this looks like a success.
598  good,
599  {{"/validators2",
600  "",
601  ssl,
602  false,
603  false,
604  1,
606  299s}});
607  // force an out-of-range validFrom value
608  // The first list is accepted. The second fails. The parser
609  // returns the "best" result, so this looks like a success.
611  good,
612  {{"/validators2",
613  "",
614  ssl,
615  false,
616  false,
617  1,
619  301s}});
620  // force an out-of-range validUntil value on _both_ lists
622  good,
623  {{"/validators2",
624  "2 invalid validator list(s)",
625  ssl,
626  false,
627  true,
628  1,
631  // verify refresh intervals are properly clamped
633  good,
634  {{"/validators/refresh/0",
635  "",
636  ssl,
637  false,
638  false,
639  1,
642  1}}); // minimum of 1 minute
644  good,
645  {{"/validators2/refresh/0",
646  "",
647  ssl,
648  false,
649  false,
650  1,
653  1}}); // minimum of 1 minute
655  good,
656  {{"/validators/refresh/10",
657  "",
658  ssl,
659  false,
660  false,
661  1,
664  10}}); // 10 minutes is fine
666  good,
667  {{"/validators2/refresh/10",
668  "",
669  ssl,
670  false,
671  false,
672  1,
675  10}}); // 10 minutes is fine
677  good,
678  {{"/validators/refresh/2000",
679  "",
680  ssl,
681  false,
682  false,
683  1,
686  60 * 24}}); // max of 24 hours
688  good,
689  {{"/validators2/refresh/2000",
690  "",
691  ssl,
692  false,
693  false,
694  1,
697  60 * 24}}); // max of 24 hours
698  }
699  using namespace boost::filesystem;
700  for (auto const& file : directory_iterator(good.subdir()))
701  {
702  remove_all(file);
703  }
704 
705  testFileURLs();
706  }
707 };
708 
710 
711 } // namespace test
712 } // namespace ripple
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::ValidatorSite_test::testConfigLoad
void testConfigLoad()
Definition: ValidatorSite_test.cpp:66
std::string
STL class.
ripple::test::ValidatorSite_test::FetchListConfig::ssl
bool ssl
Definition: ValidatorSite_test.cpp:135
std::shared_ptr
STL class.
beast::severities::kDisabled
@ kDisabled
Definition: Journal.h:41
ripple::test::ValidatorSite_test::testFetchList
void testFetchList(detail::DirGuard const &good, std::vector< FetchListConfig > const &paths)
Definition: ValidatorSite_test.cpp:145
ripple::test::detail::DirGuard
Create a directory and remove it when it's done.
Definition: FileDirGuard.h:34
ripple::ValidatorSite
Definition: ValidatorSite.h:69
std::pair
std::string::reserve
T reserve(T... args)
std::vector< std::string >
std::chrono::seconds
ripple::test::ValidatorSite_test::testFileURLs
void testFileURLs()
Definition: ValidatorSite_test.cpp:362
std::stringstream
STL class.
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:144
ripple::test::jtx::Env::timeKeeper
ManualTimeKeeper & timeKeeper()
Definition: Env.h:253
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:241
std::vector::back
T back(T... args)
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::test::ValidatorSite_test::FetchListConfig::expectedRefreshMin
int expectedRefreshMin
Definition: ValidatorSite_test.cpp:142
ripple::test::BEAST_DEFINE_TESTSUITE_PRIO
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, ripple, 2)
ripple::test::detail::DirGuard::subdir
path const & subdir() const
Definition: FileDirGuard.h:98
ripple::test::detail::default_effective_overlap
constexpr auto default_effective_overlap
Definition: ValidatorSite_test.cpp:57
ripple::test::detail::realValidatorContents
constexpr const char * realValidatorContents()
Definition: ValidatorSite_test.cpp:44
std::vector::push_back
T push_back(T... args)
Json::Value::maxInt
static const Int maxInt
Definition: json_value.h:159
ripple::test::ValidatorSite_test::testFileList
void testFileList(std::vector< std::pair< std::string, std::string >> const &paths)
Definition: ValidatorSite_test.cpp:299
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
std::ofstream
STL class.
chrono
ripple::test::TrustedPublisherServer::Validator
Definition: TrustedPublisherServer.h:112
ripple::test::ValidatorSite_test::FetchListConfig::serverVersion
int serverVersion
Definition: ValidatorSite_test.cpp:138
std::to_string
T to_string(T... args)
ripple::test::ValidatorSite_test::FetchListConfig::path
std::string path
Definition: ValidatorSite_test.cpp:133
ripple::test::jtx::paths
Set Paths, SendMax on a JTx.
Definition: paths.h:32
std::chrono::time_point
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::test::TrustedPublisherServer::randomValidator
static Validator randomValidator()
Definition: TrustedPublisherServer.h:148
ripple::test::ValidatorSite_test::FetchListConfig::failFetch
bool failFetch
Definition: ValidatorSite_test.cpp:136
ripple::test::detail::default_expires
constexpr auto default_expires
Definition: ValidatorSite_test.cpp:56
ripple::test::ValidatorSite_test::FetchListConfig::effectiveOverlap
std::chrono::seconds effectiveOverlap
Definition: ValidatorSite_test.cpp:140
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::Application::getIOService
virtual boost::asio::io_service & getIOService()=0
ripple::test::StreamSink
Definition: SuiteJournal.h:114
ripple::test::StreamSink::messages
std::stringstream const & messages() const
Definition: SuiteJournal.h:134
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::ValidatorSite_test
Definition: ValidatorSite_test.cpp:60
ripple::test::ValidatorSite_test::FetchListConfig
Definition: ValidatorSite_test.cpp:131
ripple::test::ValidatorSite_test::FetchListConfig::expiresFromNow
std::chrono::seconds expiresFromNow
Definition: ValidatorSite_test.cpp:139
ripple::test::ValidatorSite_test::run
void run() override
Definition: ValidatorSite_test.cpp:400
ripple::test::ValidatorSite_test::FetchListConfig::failApply
bool failApply
Definition: ValidatorSite_test.cpp:137
ripple::test::make_TrustedPublisherServer
std::shared_ptr< TrustedPublisherServer > make_TrustedPublisherServer(boost::asio::io_context &ioc, std::vector< TrustedPublisherServer::Validator > const &validators, NetClock::time_point validUntil, std::vector< std::pair< NetClock::time_point, NetClock::time_point >> const &futures, bool useSSL=false, int version=1, bool immediateStart=true, int sequence=1)
Definition: TrustedPublisherServer.h:714
std::stringstream::str
T str(T... args)
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::test::detail::FileDirGuard
Write a file in a directory and remove when done.
Definition: FileDirGuard.h:107
ripple::test::ManualTimeKeeper::now
time_point now() const override
Returns the estimate of wall time, in network time.
Definition: ManualTimeKeeper.cpp:37
ripple::test::ManualTimeKeeper::set
void set(time_point now)
Definition: ManualTimeKeeper.cpp:81
ripple::test::ValidatorSite_test::FetchListConfig::msg
std::string msg
Definition: ValidatorSite_test.cpp:134
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
Json::Value
Represents a JSON value.
Definition: json_value.h:145
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
std::chrono
std::chrono::system_clock::now
T now(T... args)