1#include <test/jtx/Env.h>
2#include <test/jtx/envconfig.h>
4#include <xrpl/beast/unit_test/suite.h>
5#include <xrpl/config/Constants.h>
6#include <xrpl/proto/org/xrpl/rpc/v1/get_ledger.pb.h>
7#include <xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.grpc.pb.h>
9#include <boost/filesystem/operations.hpp>
11#include <grpcpp/client_context.h>
12#include <grpcpp/create_channel.h>
13#include <grpcpp/grpcpp.h>
14#include <grpcpp/security/credentials.h>
15#include <grpcpp/support/status.h>
30 "-----BEGIN CERTIFICATE-----\n"
31 "MIIFhjCCA26gAwIBAgIJAL9P70zX30oiMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV\n"
32 "BAYTAlVTMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRgwFgYDVQQKDA9S\n"
33 "aXBwbGVkIFRlc3QgQ0ExEDAOBgNVBAMMB1Rlc3QgQ0EwIBcNMjYwNDA5MTMyNTA2\n"
34 "WhgPMjEyNjAzMTYxMzI1MDZaMFcxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARUZXN0\n"
35 "MQ0wCwYDVQQHDARUZXN0MRgwFgYDVQQKDA9SaXBwbGVkIFRlc3QgQ0ExEDAOBgNV\n"
36 "BAMMB1Rlc3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzOJ5s\n"
37 "dy1O0GN/kmbeWf5DmFbQBSS9FRKxh6/o9V9BqRBQfECrVK9T5Y4FYrGGtmUW3YEV\n"
38 "uMDZ5q6rvBT2zrrzPXnWA5Pb4I4mKqC/yk5L7Mm8A9xQsNoRzgTyl/NuHiXKn+yQ\n"
39 "FuidA6U36qwIAcDR7gLqrJ1ud/ng9f9Q4k6+IItY/XGhcz4nKlQq9jpzmfdSlBkU\n"
40 "hXsIsdNtC+UGlQMCMX2jwysIFfjjCOMlH7KFQ3dKodhsW+Ym6AsPwyRGCgNXO/zd\n"
41 "Fqt1MIMs1F7r40DtfVO3R7w4/2SblcceZlsDrYQUbJnH+sEPWO0SGGo6Y7Ohs09+\n"
42 "aJSOAGGQVgTSLuAcFtR4BXD0GLn39+10PDvHGOsMJKL1de1f96s8kPlifQ5AGWuc\n"
43 "xy6XsupGSa0F8LozwQmKD7hVkyladUTWFPknz5tsPEVApTO0U8Vuknuhyovo6+mx\n"
44 "qBoSD32NwHveFz3jWqfj0CGX9BwL9AOpMabDhROVQfyM5GrLeLOOdgOnsBXJYYdW\n"
45 "MeJwz6BH30q9yvEd9Ti26jSk3fM8WPuEkZzNNp8STEMyDrfhaKOe5fGPWLnqMQAf\n"
46 "yMCDLwB1WqIN1Q6gOELb3rxyYDVH/5x6/JXosdUe1qx/tzvRoSWxxssRRd2Em+e+\n"
47 "MUFLXz+9D6kZ9XCuP/mLyRGW6LEiwwQkGKMnzwIDAQABo1MwUTAPBgNVHRMBAf8E\n"
48 "BTADAQH/MB0GA1UdDgQWBBQPK5hXxLdTj3QqfVzGpfTga6IF3zAfBgNVHSMEGDAW\n"
49 "gBQPK5hXxLdTj3QqfVzGpfTga6IF3zANBgkqhkiG9w0BAQsFAAOCAgEAa06whkqv\n"
50 "KmdT1HVhkV7AkWEAeHMWPLLaaFbcwble7a1Vizh6GjCyNpLtoN+mtwqwiOdsIlRE\n"
51 "42pWILc6CuuX0ae0nHSrcQS5mq8ZKSMr1xTo9RSfBq7CDfdyquxzG83HhpdApViZ\n"
52 "87Bjy3WoRuomM+YiONfUVdCbC5ZmXW/z+xrXJ+JqIXrtv66sZxpQIR0+ShnWT0DE\n"
53 "w9jB5fxjydPFwEudYi4z9XjEZaZJ1f8VNWDuUvi3yTJtTlNaWnKveudtDZBw/fA+\n"
54 "MBFd9ccYVhGQPxOs6S0Ev6q5IjcnzGeEBNZOjgjQk9aFrAs2Iiy018AbYQj5XD64\n"
55 "hHyiNgyPjl/VgXJE1Xl3lXGpiiJlXctgnCd3UGMfKznhBIpDT13i2CmHFyR3uk7o\n"
56 "UOZUXCnbnmgthejmFxB35Wf5TmGaYubtRMfCPHGNbQD+7Kg2+8eel3J3JSuG6RQ8\n"
57 "hwNyHHQnaPVUSANItJ4cMe5DutM0vUCMkJbajL+fjC5SdsTcGfR2VmAFqulNDXjH\n"
58 "sGWBiWVNsgddax63m6kL9UOeE+8pu8yStKZ4mVn2EjE9eJk4vyZt4BaI6sDUMlke\n"
59 "S9OjcI5iYlxXNgbRQBtwK70+c3D3JoRPREkTRPPwC4NiAFed7UwXSMh5nWbpt/dq\n"
60 "fAbAYqu0rfMFHUYjzIVnu8WRCC56qYHO5tU=\n"
61 "-----END CERTIFICATE-----\n";
64 "-----BEGIN CERTIFICATE-----\n"
65 "MIIFizCCA3OgAwIBAgIJAIErcpMflkrRMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV\n"
66 "BAYTAlVTMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRgwFgYDVQQKDA9S\n"
67 "aXBwbGVkIFRlc3QgQ0ExEDAOBgNVBAMMB1Rlc3QgQ0EwIBcNMjYwNDA5MTMyNTA3\n"
68 "WhgPMjEyNjAzMTYxMzI1MDdaMFExCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARUZXN0\n"
69 "MQ0wCwYDVQQHDARUZXN0MRAwDgYDVQQKDAdSaXBwbGVkMRIwEAYDVQQDDAlsb2Nh\n"
70 "bGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCv+Lj9LJfPuSOE\n"
71 "yZqTn2gmG5tJt02ywnuIQet7N5tduxnNs50yXQ00Jeb40dth0HwI5I+AsEVNPIG3\n"
72 "7tJ9RtCwwTyltaZ4bXuL9ujEVr6TAKY6rlU9bL+Zmr62Lm8B0SLouxfPtyzKhBv6\n"
73 "7bGUrdIX7o9DbTQ3/2mQTc7KjPCJTEutmpVyD3dABN1qDM9Qzac0NtK1nixvYGd4\n"
74 "SpbK95BRXby3X9um0dVXoUMbc2gDV9uUZw1xLSjuKDJtQ/rleqe0mmS6JSoagwbb\n"
75 "DmPX/GbIf21IWUsg3m7AyIwYf9FtIJArB/j3iVBsY9lTB0mXSLxiyN6KM822+QjH\n"
76 "/VeHKDUWdQB6N3smmi1OLQasukRpSUTmTsoucn30dUqS6qdTtkHzvqGEN+CXBWgG\n"
77 "i1AS2CacOjYSVHRppC10r/3kEChYY/9rqYBz7GedFRJ6VzQzrwFYZleLJvX6GWfe\n"
78 "4gNvgwLfo/q2Af1HkCY2aHO+19eAghVsy1MRUDnm/GbZAhHSrX10iEfRjs+GhfxY\n"
79 "v0xMrvGBCm/2CiJ8RAvdRPpNkM/3u9fjOmqdKvE9NTqDOX1HUBoqa/UguIzi6o/k\n"
80 "BlBtohfaeL6ZeYXl6MefIIs2pipR7S1VQ1RY9OSdnN5nIJidyn1l85P9vLn49QVw\n"
81 "2OAT+TcEZnxyaiHCKU6nWtusuMt3wQIDAQABo14wXDAaBgNVHREEEzARgglsb2Nh\n"
82 "bGhvc3SHBH8AAAEwHQYDVR0OBBYEFO9bPc31jmMlMVNhOd+eXgZPD/+pMB8GA1Ud\n"
83 "IwQYMBaAFA8rmFfEt1OPdCp9XMal9OBrogXfMA0GCSqGSIb3DQEBCwUAA4ICAQCm\n"
84 "+hnvRdr9N9a260yOD53b/Gs0c4viAOU3WmxAa89upLHnpPEi7/GlKlw+ed6SwYoX\n"
85 "CSopDw8AG2Ub/oHM3uIrONjfdHBwUl/SUS8wNhiELuQjKm0qGjkh/n/FHY903flc\n"
86 "0VP2ciLnqhSS2NY+KH0O8uny3yR4FVH7Byqtk648Z7LfIhe02TjTIjhXDrGwn5dS\n"
87 "tuTKEAGaxxPJuINCR1BZlwfk+10ipJK59rSpCW//P1YJVr16sdnyh3YJXoAJ5qxP\n"
88 "P8QWHiRIl2ZGs7KB5SU9fX1dVEU5gwrl/KF3oP+iS01wfNZGvnR+eHMPJsl/IwoC\n"
89 "SOZAMjgkTZh06cprfEXne8bcidiHvETbF9szMAofA91PbXi0lcwMqpkHG2AElOXI\n"
90 "by4ejjs9RZJF2Ef38qZPb8RuT+gLORFH5SuPQUwXKlszjpzpxkQ6IKYjFJY+j8CS\n"
91 "XlXhdkzK5h18cf7J2i5SQdIzE1btQqdcaMb9DzX+drCqqD8JZd1Vczua7Q5tbZ/g\n"
92 "Bq19Zzo1KQL0xXPdomWv+sP6eUMiW+3J5oFN2hJpilKuFSCAhDmgcmLooFy5t6rR\n"
93 "kW0n1P3iTWvgQHNzB/3msanvC4/hHyrHHOVGQtAjhxuoRioBJ+hg4RKDptSUcHJX\n"
94 "YSyd81wvumIpP+I7BDkQLgTb+NzMmoBIjRg3aVvXSg==\n"
95 "-----END CERTIFICATE-----\n";
98 "-----BEGIN PRIVATE KEY-----\n"
99 "MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCv+Lj9LJfPuSOE\n"
100 "yZqTn2gmG5tJt02ywnuIQet7N5tduxnNs50yXQ00Jeb40dth0HwI5I+AsEVNPIG3\n"
101 "7tJ9RtCwwTyltaZ4bXuL9ujEVr6TAKY6rlU9bL+Zmr62Lm8B0SLouxfPtyzKhBv6\n"
102 "7bGUrdIX7o9DbTQ3/2mQTc7KjPCJTEutmpVyD3dABN1qDM9Qzac0NtK1nixvYGd4\n"
103 "SpbK95BRXby3X9um0dVXoUMbc2gDV9uUZw1xLSjuKDJtQ/rleqe0mmS6JSoagwbb\n"
104 "DmPX/GbIf21IWUsg3m7AyIwYf9FtIJArB/j3iVBsY9lTB0mXSLxiyN6KM822+QjH\n"
105 "/VeHKDUWdQB6N3smmi1OLQasukRpSUTmTsoucn30dUqS6qdTtkHzvqGEN+CXBWgG\n"
106 "i1AS2CacOjYSVHRppC10r/3kEChYY/9rqYBz7GedFRJ6VzQzrwFYZleLJvX6GWfe\n"
107 "4gNvgwLfo/q2Af1HkCY2aHO+19eAghVsy1MRUDnm/GbZAhHSrX10iEfRjs+GhfxY\n"
108 "v0xMrvGBCm/2CiJ8RAvdRPpNkM/3u9fjOmqdKvE9NTqDOX1HUBoqa/UguIzi6o/k\n"
109 "BlBtohfaeL6ZeYXl6MefIIs2pipR7S1VQ1RY9OSdnN5nIJidyn1l85P9vLn49QVw\n"
110 "2OAT+TcEZnxyaiHCKU6nWtusuMt3wQIDAQABAoICAQCZilzm0uT3Y2RBdaMBUaKP\n"
111 "NaFONbl+00D0SAhOr9tJcnp2SFVN33Eo4jVhP8K62y2OmNc5gxRE6xmIQsK4enSW\n"
112 "9VSUhiXliCm3m03IGqQYIgXox7oqaVvYi/QBhAxpunBKPwzsubhET/cWABXlU7Ew\n"
113 "HoA0ZfGdNqeGOM3JYCZ0tfSGWo4xQptbaaND6D9wErDk1z0NKSE+YRCHHhXqrQ3o\n"
114 "YPDL08EVEpui5VtndU/5Msyt9Sj+alf/TWWKfzlIx7fS1rAy10Cgd1khA7JMf7ez\n"
115 "E7Rn3zm1ST+7yICs08IJBNOmKEOswMxCdvDmCELG1LlDPF8omUDSeQKXdU7M6GFA\n"
116 "b5PQ11Ik6xZVw1NUESf4d9g0VhEJRXSdGwA3KepAkwRejkB5jI56C8z9dB0LWdWH\n"
117 "2r3dX2ZpbJv0XVNxAELRgKwyfqWxYrF3caGLrxxWAiyPFvD9FgZJB1ftBU3D+HZZ\n"
118 "bltdfHJBgZe3pwoCr3X2JPhcA6ecITsset14dvsXHSi9IAXTHbeXxjrHCRcXs6xV\n"
119 "v4ZSL5r43dv6qk7XiFONCmV8diIwJOxcaSvoBgeeCykX4RKGSk/6Atlo4C9hXb47\n"
120 "BAuXu3Y+SkS98EljsdeNKCr013Tvt0p4H2QfeoDTKuzC+j3hu9fCkEP3oak2nWFl\n"
121 "bOkrYMJCc6yxu20G58vzrQKCAQEA1y93gNuNa7Z+VrZCSEcJX2BZl1mTyhLEa9mN\n"
122 "QOmKlW10VrfCsJxLu+dTGWccy0c6Q8wk6uGjgYJHsdyFPIdSroPR2ysJKSP/5Vzu\n"
123 "xNymgbeLPnWoivC9TctovWY/15fdboYNUO54jOpFheCC1wq9ZP6CyJmw5O96Y7tJ\n"
124 "1l5Dq7Fe4iQbIQHPt54wVVHsm7G1ZNywgSbt0HXHeP43YN3mRawJ51++MaEksCXv\n"
125 "rW+vOxPdiW8djE0tqcK0tqFMhI6p+WcUu8128aRHd0iHlKsVsFU4OLLZr10zwy9i\n"
126 "COHoF4Fh53pGp05jv+5eMtuEiem87ZUmpJn7whHZt8sKSE71AwKCAQEA0Vkwr4KA\n"
127 "kRRCUPvor5mdNil05N1mLrYgr/4UAHg3tbeTGxOjSX65KnJWi5dsDmZUdGTL4StD\n"
128 "8H6uLzzjX88gQkpKvtRYPYKBFtTRsI+ItOvIIo8czK/Kv8dwC2WXZbZBjsCAhrCm\n"
129 "0fKL2jx7rgdjaqvQeqSRtcHiyiYJG/jC7Iqwm4CyPr+nkVUWKZUWXopw0QXZXHWp\n"
130 "Glz9TXreEI7Xb/R+RXYU21exBqg0SfHq9pA//aNTQWxWGlNVwqO/KUao9HZupKHb\n"
131 "mA73oxFJTKhVNNNdC5cC91pxDeDTUzpIEjCGeLI3Aa35CD0WFqEbELJphr5HGkGo\n"
132 "VkYod6P79+Ta6wKCAQAadFpzvAop2Ni1XljNu/X6BMVe5wNVT3NYcvl7pnqEHl20\n"
133 "H4lO3xgsdKbxs4yFrS8LkLhlK/JHBLY9toemxlgy3j/ZevP4W9Wk5ATyrNHHlsIG\n"
134 "nr5mvmv3eW9aAY0Nuzzczpwqe/bUFCUR7WUIfOiF1whLEyH9MzfPtQHB2frly7uH\n"
135 "f7raFvfrcgYtJxI4neNYEA2fAyMvgptQU6iJPx6FKD5bdJjUTyRMh41svBNF5w5Q\n"
136 "TBnM2twnR6mh3jii/0sEP1j8MalS0ch7cK5CZ7oV4JQ13D8I4SNw9o1N3EAFS8G2\n"
137 "jIDNJsT6npp0FCq6LcMtTi3fBJM/66PhhZOxCgvzAoIBAH1LnE/vE3PBZE+D9afj\n"
138 "kKwx87xmphme98FdmCsPyIgB7xFtl3UNW1WESTgS0KFtrW5cRYnmkysFJssu7gcR\n"
139 "uIT0YfgErythSFGZ3kaGIZPm6kmEzf/T1s0hWHX5v7soceQ2YrY6VB2jxQBA4uUt\n"
140 "ltrpKkW86ViXSl0ilqEfKcrY1wq64/OaUXgyLKmGiXTb9tmjXoxv/12/+fq9ZtsS\n"
141 "Iu7mrgx0t9bvjQwm7+Sx3abkfugXMGUfqgjnh5SO3IKfv89QcrgmB3/itWPrnKs8\n"
142 "tIKBXlbpcuUIRFHCFbjiUPBSCqmCQFnI/htoNCgnFEPSBEaY64VTdqTsKJwykUO0\n"
143 "vTECggEAEAB8vyHHk7fpU+IOwD8TP7MCMHwoJzoHQp35So7TlhmO7oDranNhg3nl\n"
144 "jhTOeISLG2dmPkT49vhsO30tal4CgSXVZo1bPbOK83UvgeLH5Rhji44Dmah+ohKy\n"
145 "wCuVLuF6YSSp5rD7VIrahhegBFXEYdW5+ZBFbDpE5EXp0WeHc7IRPwWvm+ixr1m8\n"
146 "VqLeeh1xkMG5WdTTwGjgKWIFXZQ3bOIdVK7uya8wFDAtftkswXiBxAlb9L6Id+Dp\n"
147 "bKfMAHNouU1TQn5duFgPnCbSU1Js74HkkC0NEEIjQX8k2UCPrhV0VfLfViPuPFax\n"
148 "S/RYUSUkZ4VvqFUfo7wT8x18urb87w==\n"
149 "-----END PRIVATE KEY-----\n";
152 "-----BEGIN CERTIFICATE-----\n"
153 "MIIFeDCCA2CgAwIBAgIJAIErcpMflkrSMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV\n"
154 "BAYTAlVTMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRgwFgYDVQQKDA9S\n"
155 "aXBwbGVkIFRlc3QgQ0ExEDAOBgNVBAMMB1Rlc3QgQ0EwIBcNMjYwNDA5MTMyNTA3\n"
156 "WhgPMjEyNjAzMTYxMzI1MDdaMFoxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARUZXN0\n"
157 "MQ0wCwYDVQQHDARUZXN0MRcwFQYDVQQKDA5SaXBwbGVkIENsaWVudDEUMBIGA1UE\n"
158 "AwwLdGVzdC1jbGllbnQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDP\n"
159 "QHttw3TLjOqYS3VkLF3KMRaP2ZtO6A1mXfTbqbKvD41Fazf/cM/v9lPMAlRd2SEY\n"
160 "3MeE8KVddKJwsbF0kNgDkKB5D5V42WrTw5biFNMOeHAZMR/oWChIvZbbGbDxIdIO\n"
161 "2+W3X0kjpa2eKcK9qBk8xoyIeilyXtleGWuWvHxiZP9iGHxaTWB+wIKUIK6vrEOb\n"
162 "iO3P/9XPpHzsBt0HdTDh4V7fwnr2UndVeQyBwUwLn6pd73sTKBfA26YppRwDjPIj\n"
163 "6NYtF3I28lRCUo+47TAVZM97gjN9oEwyHIVtOc7fnZPwtN26M5v5083SGXU1k/PN\n"
164 "3xGAlDUiCF3RSMbBRylGgUVtsAD57i8tI2SqCr+ZG233VFiOdwTRKKVNTyMC9TCJ\n"
165 "dCFFEDFDHTTSimKRQKy0Cm2qoL6JBkziAIiu/0Zzv9YjAAnRoJ2cweMXQ/9z1oWe\n"
166 "EUZBLRsggYQ8FbM13FOkOs8IlzacSuhwrYKOq8LsMX4cH2mnn783FtXXqrL/xfL7\n"
167 "11KhzGpZNrz187ilJ+ZsmP9D6vCBP/tR7V52dgtB6I291o8zxdH8GheIGenEFaZa\n"
168 "oAwyN2FuJgXZqx9319I9gYerZ/BbUzA2MuOxFd0ywtdcTPqKiyAQ9rxQVCVQyYWj\n"
169 "kfBEYRzWxjfj3XhNprxdm3cauz01NAoTDiz52dZhGQIDAQABo0IwQDAdBgNVHQ4E\n"
170 "FgQUXVKwiGRrXC1sjK2D86jsjMVV0XgwHwYDVR0jBBgwFoAUDyuYV8S3U490Kn1c\n"
171 "xqX04GuiBd8wDQYJKoZIhvcNAQELBQADggIBACpHTm9GZMZ7OPhqVo4VltVOW9a9\n"
172 "LLDsVYmvpAF9+yjZGims6+p3f7eY+o+TRdUE4HEBCmH0UiFVODXCZSoqXo6y9xq7\n"
173 "TS1dmXll1Sajbfi7YXsM8CAUb+cSsHtmT57JtbGicDiVXAqIOlT65yXkuujdcEa0\n"
174 "OAw45vJDkWk/6nneFJKdTs7aT3fvIGTlMAxgMJngVsA8BRsX8TWoo05Lum8ClNgi\n"
175 "s6mtl+nUvjOaM0omFL/K9kqLy7OJAbmE5xuhkC9q6Kn0pHBL4u0YSWaWTpyrvAX7\n"
176 "BuOE0G1JezcCAcqJvXbKFvhnOSHTvzdlMgXhteGW8Uwgf8cGKtVLSwh6YTjI1XaL\n"
177 "DkNZfJabAyH7BsGGbAd9Jts4h+4auPqHgcpEz16280oCgZdcfLSP0UKrfwYuXOar\n"
178 "8KWlVRFl2NBpEJwRf2KjZFQUqYoX1MmfX0gyy+kk0ZP12L7oGNqAxkaWySfb4PSv\n"
179 "Hsnb8iD6sIJQjZvZ/2wLV8xwFTbFjvGbmSx+XLnMUVV8cVAMUpZz5X2R9pBvpVi4\n"
180 "KfUccTvIVA0p1wFSdWYQ0+QNxHxZGX1rin6KVUdV1z8K6J3FgGlRqzfz4bruGpXs\n"
181 "6vX5vqF9KTFpwLTOxDU+kAoIfHowHeu/LQX1l+rk1ww2UZQ1zvgKb6fxWMtviq3F\n"
183 "-----END CERTIFICATE-----\n";
186 "-----BEGIN PRIVATE KEY-----\n"
187 "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDPQHttw3TLjOqY\n"
188 "S3VkLF3KMRaP2ZtO6A1mXfTbqbKvD41Fazf/cM/v9lPMAlRd2SEY3MeE8KVddKJw\n"
189 "sbF0kNgDkKB5D5V42WrTw5biFNMOeHAZMR/oWChIvZbbGbDxIdIO2+W3X0kjpa2e\n"
190 "KcK9qBk8xoyIeilyXtleGWuWvHxiZP9iGHxaTWB+wIKUIK6vrEObiO3P/9XPpHzs\n"
191 "Bt0HdTDh4V7fwnr2UndVeQyBwUwLn6pd73sTKBfA26YppRwDjPIj6NYtF3I28lRC\n"
192 "Uo+47TAVZM97gjN9oEwyHIVtOc7fnZPwtN26M5v5083SGXU1k/PN3xGAlDUiCF3R\n"
193 "SMbBRylGgUVtsAD57i8tI2SqCr+ZG233VFiOdwTRKKVNTyMC9TCJdCFFEDFDHTTS\n"
194 "imKRQKy0Cm2qoL6JBkziAIiu/0Zzv9YjAAnRoJ2cweMXQ/9z1oWeEUZBLRsggYQ8\n"
195 "FbM13FOkOs8IlzacSuhwrYKOq8LsMX4cH2mnn783FtXXqrL/xfL711KhzGpZNrz1\n"
196 "87ilJ+ZsmP9D6vCBP/tR7V52dgtB6I291o8zxdH8GheIGenEFaZaoAwyN2FuJgXZ\n"
197 "qx9319I9gYerZ/BbUzA2MuOxFd0ywtdcTPqKiyAQ9rxQVCVQyYWjkfBEYRzWxjfj\n"
198 "3XhNprxdm3cauz01NAoTDiz52dZhGQIDAQABAoICADTppZmUeVEunQZc3Y/BtABX\n"
199 "IAeB6yDuJd2ox0b9wFzpf4vln9pblvsQzLwdLCT5tnV+iIHsXovJp19WPpQgFsZy\n"
200 "OkYuMF82Qwvlt7Po1Smwng4QeLD9MOvBW658lKw7kkGw6qkybp3nQrhKuSlqrWbS\n"
201 "2jZN2h8VEDHyE4HchXUpi/ojfjwf3S7/P1dKMM8xD+G5x91+17u3px0rc2rgBKbm\n"
202 "vy4pnPMegtETopnOG/grv3dUGPv/FHFsorOnL8vIRFnerC+++K4GmHSGV6NDCy+r\n"
203 "GT3TNAoyzsFMftQwGh0FQiwGQUW0v3G9HaMyVLZlG63H8dP+AsK5mBpCllvqKyMb\n"
204 "TQcS8mTBYAvBgiKqZBy6cwbnLaN5hYftDTg4zS62LVZzNlaMeTFGGYINDrth2S6X\n"
205 "+qH2GcXAUqd8aYIz/BLimCGhZMFQ0hAFCcq72Lh8UJsvvf9ng8Di/6oiZFJeN4nf\n"
206 "/LHUjlOyBqj8prTh0UCBjM0hdzzs96K+e3eBGjFHdVrdK5QytKZh1KTBSu0t64b2\n"
207 "0MSW5+2vFbdaQT5jed2lyh9YMmtGJV07T+5LKjWQGcJcc53DLA6uQ8lQuckQReE4\n"
208 "VzTWoG0eKEvk8ahltbl+0Gk7+fQlsMD5VizbET7EDOoiFPT3SpA/5dybXglNSuH4\n"
209 "9T65s7Xj2/zD8khLb3CxAoIBAQDwV3OQ66kqIC554Emz7F9ZNInMx4Vjuatd4wxe\n"
210 "WMT1Vlyg0ZeNSgdfggPmfntDW56NZ/h7q9F9feGfF3OogfZXVv2NzsynAOS4DR1c\n"
211 "0JR8/y7NG8vxHmDkNVJ3YkHfNYqK3x+sMCoXF0jDdaILXaP0nzAdcnLrRLyU9F3r\n"
212 "RVJpyaMWt9mtnRzlf1PTlc9WQ99MYuMfqxFj/zBFddnNFiI0FaG3/3Xdg6EH9x42\n"
213 "/2GXT/TlSUQo4e6Dh9mGhupUYzJt+AqjCnFA2n+D68QIdVq8ykOqGvnpwmfF94qt\n"
214 "8xfrKhI4zskj4N0X/xwByfEBOkU8nI8zP8PdVqKCbCRG1Z93AoIBAQDcwSRpPD5J\n"
215 "dmfXY2MGHvGQiJme/3YGPhcA15fQVRzWuZtn1PHULlI2V62NintzTUhjmv6SkGyX\n"
216 "6ze4RSCxrRFJumJwev5HtohQ7DH/nDtg+Y9Ewn32ehSEotycz1HUskOtgtLOQjwY\n"
217 "m66gTx6OzG4T6G2YRHcK8hFk9eLR0t2fIqPtu6APfRuo5OowiuYVzRKOplzh2J05\n"
218 "Q1TCJ4QL6geJQ/MzxVx33yopXWfRxZekG7ri4OJTIv8zj1Ocrytgz4hxAc8xJEf5\n"
219 "Z50k4JaWGBy+O/mKZ9sOGsolNv/FMUauE2EjSeNWNgvCFFvh4hDUciIakPzEeslp\n"
220 "hZdZCG9IV8fvAoIBAQDoDbfSbAc4Wjwlhq4C362sJrMKGnarNADGtMsjaRg6PTlQ\n"
221 "OS3XyGtYBuOXL/X5skNjCsj7N4kcXmdywST1xQ3BhIdp3QryEEXFgzwfenB0Q7q/\n"
222 "ZSBDXW51yRonlKI/TqXGseoVyadKBjxGJJTh3nbIYM8HD5Lvn71pIIxx9cu9wmcK\n"
223 "L1cobvMQjyCzwQigpQW77hqXYAd5glHsLv6tKrq5iU1Mp4X46/eWBj6RIYDrpNKy\n"
224 "c0wxIPu22XrojelAs0pkrUIv64wv7weBqyjqdcy3TZ+JZWR5FDA4D2tByt4EO+m+\n"
225 "GcJRNvKiEbnL7FwbMFTbUdpdxCpr0hM0VA+uqOG/AoIBAB24JuXABYawWSSHLdKq\n"
226 "Ic1ahowASmxmuYQUgky62KoTzNc6tN/i6JCGV0gh56LLOb6nJDSpGuWM9jBpphAl\n"
227 "g5lQbWZFOKyA53M1iTmnV9sjXeVc5cZkAxUkM90skBC5eyEF5sl740lQ1D6iyDNj\n"
228 "VEJ73R1NwlUH582WyNWEtO9yo20jAFZ1el7PirPET1uKA0CPJxwEpI4MAYIt/bn4\n"
229 "5NDXBAvpOxysP6nX+F0mY9blINDgg7e7k23mktQaRRXAetbz7mfoQYRTLbXEQqGs\n"
230 "V1pJCrxWZQhOFP7Tm7V5f9F5rG8qyF9X4VdclE4huDBRuUOoV09AVJNPN+P1nb24\n"
231 "i6MCggEBAIHUb8G0QKM4LPfdUmv575YmbnYY+Y3O982+jjRg4uAkYHnEkNfL6FKE\n"
232 "6ot7vcwDTN2Ccw6UKZU8GvyAQOGotmj6Nkgny2wFnEfoTzJaENjhPlnCHD9LDCps\n"
233 "w/tuoCHOUyyEb/Ygc+4xTsc0W3y2dbaYcg1qvLeIFuVZBNvY1XNlVf40/sVoiyet\n"
234 "Abh2yPwqOgOu8FpK4gcM8iSwL/xhEJJgT2wE+1MyHOd8KKklFHR7dF2WX1dF0Sif\n"
235 "cerPwqKXCvWh7og0RIJXe24fymMxtIsURBer9a3bPzUPVQoOXki4/u/kdEGH66GH\n"
236 "+6f4hsbp29hg+BUZ+UPdk7QyCKpZD1A=\n"
237 "-----END PRIVATE KEY-----\n";
245class TemporaryTLSCertificates
248 static constexpr std::string_view kCaCertFilename =
"ca.pem";
249 static constexpr std::string_view kServerCertFilename =
"server_cert.pem";
250 static constexpr std::string_view kServerKeyFilename =
"server_key.pem";
251 static constexpr std::string_view kClientCertFilename =
"client_cert.pem";
252 static constexpr std::string_view kClientKeyFilename =
"client_key.pem";
253 static constexpr std::string_view kCertsDirPrefix =
"grpc_tls_test_";
255 TemporaryTLSCertificates()
259 boost::filesystem::unique_path(std::string(kCertsDirPrefix) +
"%%%%%%%%");
260 tempDir_ = tmpDir / uniqueDirName.string();
263 writeFile(tempDir_ / kCaCertFilename, kCaCertContent);
264 writeFile(tempDir_ / kServerCertFilename, kServerCertContent);
265 writeFile(tempDir_ / kServerKeyFilename, kServerKeyContent);
266 writeFile(tempDir_ / kClientCertFilename, kClientCertContent);
267 writeFile(tempDir_ / kClientKeyFilename, kClientKeyContent);
270 virtual ~TemporaryTLSCertificates()
276 TemporaryTLSCertificates(TemporaryTLSCertificates
const&) =
delete;
277 TemporaryTLSCertificates&
278 operator=(TemporaryTLSCertificates
const&) =
delete;
279 TemporaryTLSCertificates(TemporaryTLSCertificates&&) =
delete;
280 TemporaryTLSCertificates&
281 operator=(TemporaryTLSCertificates&&) =
delete;
283 [[nodiscard]] std::filesystem::path
284 getCACertPath()
const
286 return tempDir_ / kCaCertFilename;
289 [[nodiscard]] std::filesystem::path
290 getServerCertPath()
const
292 return tempDir_ / kServerCertFilename;
295 [[nodiscard]] std::filesystem::path
296 getServerKeyPath()
const
298 return tempDir_ / kServerKeyFilename;
301 [[nodiscard]] std::filesystem::path
302 getClientCertPath()
const
304 return tempDir_ / kClientCertFilename;
307 [[nodiscard]] std::filesystem::path
308 getClientKeyPath()
const
310 return tempDir_ / kClientKeyFilename;
313 [[nodiscard]] std::filesystem::path
321 writeFile(std::filesystem::path
const& path, std::string_view content)
323 std::ofstream file(path);
325 throw std::runtime_error(
"Failed to create file: " + path.
string());
328 throw std::runtime_error(
"Failed to write file: " + path.
string());
331 std::filesystem::path tempDir_;
344 grpc::ClientContext context;
345 org::xrpl::rpc::v1::GetLedgerRequest
const request;
346 org::xrpl::rpc::v1::GetLedgerResponse response;
351 grpc::Status
const status = stub->GetLedger(&context, request, &response);
367 Env env(*
this, std::move(cfg));
370 auto const grpcPort =
372 BEAST_EXPECT(grpcPort.has_value());
374 BEAST_EXPECT(*grpcPort > 0);
379 auto plaintextStub = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
380 grpc::CreateChannel(serverAddress, grpc::InsecureChannelCredentials()));
387 testcase(
"GRPCServer with valid TLS configuration (no mutual TLS)");
394 Env env(*
this, std::move(cfg));
397 auto const grpcPort =
399 BEAST_EXPECT(grpcPort.has_value());
401 BEAST_EXPECT(*grpcPort > 0);
407 auto plaintextStub = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
408 grpc::CreateChannel(serverAddress, grpc::InsecureChannelCredentials()));
412 grpc::SslCredentialsOptions sslOpts;
413 sslOpts.pem_root_certs =
std::string(kCaCertContent);
414 auto tlsStub = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
415 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOpts)));
422 testcase(
"GRPCServer with mutual TLS (client verification enabled)");
429 getServerCertPath().
string(),
430 getServerKeyPath().
string(),
431 getCACertPath().
string());
432 Env env(*
this, std::move(cfg));
435 auto const grpcPort =
437 BEAST_EXPECT(grpcPort.has_value());
439 BEAST_EXPECT(*grpcPort > 0);
441 auto const serverAddress =
"localhost:" +
std::to_string(*grpcPort);
445 grpc::SslCredentialsOptions sslOptsNoClient;
446 sslOptsNoClient.pem_root_certs =
std::string(kCaCertContent);
447 auto tlsStubNoClient = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
448 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOptsNoClient)));
452 grpc::SslCredentialsOptions sslOptsWithClient;
453 sslOptsWithClient.pem_root_certs =
std::string(kCaCertContent);
454 sslOptsWithClient.pem_cert_chain =
std::string(kClientCertContent);
455 sslOptsWithClient.pem_private_key =
std::string(kClientKeyContent);
456 auto tlsStubWithClient = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
457 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOptsWithClient)));
464 testcase(
"GRPCServer with cert but no key");
477 Env const env(*
this, std::move(cfg));
478 fail(
"Should have thrown exception for incomplete TLS config");
482 BEAST_EXPECT(
std::string(e.
what()).contains(
"Incomplete TLS configuration"));
489 testcase(
"GRPCServer with key but no cert");
502 Env const env(*
this, std::move(cfg));
503 fail(
"Should have thrown exception for incomplete TLS config");
507 BEAST_EXPECT(
std::string(e.
what()).contains(
"Incomplete TLS configuration"));
514 testcase(
"GRPCServer with ssl_client_ca but without both ssl_cert and ssl_key");
528 Env const env(*
this, std::move(cfg));
529 fail(
"Should have thrown exception for ssl_client_ca without TLS config");
535 "ssl_client_ca requires both ssl_cert and ssl_key"));
550 Env const env(*
this, std::move(cfg));
551 fail(
"Should have thrown exception for ssl_client_ca with only ssl_cert");
557 BEAST_EXPECT(
std::string(e.
what()).contains(
"Incomplete TLS configuration"));
572 Env const env(*
this, std::move(cfg));
573 fail(
"Should have thrown exception for ssl_client_ca with only ssl_key");
579 BEAST_EXPECT(
std::string(e.
what()).contains(
"Incomplete TLS configuration"));
587 testcase(
"GRPCServer with ssl_cert_chain but without both ssl_cert and ssl_key");
601 Env const env(*
this, std::move(cfg));
602 fail(
"Should have thrown exception for ssl_cert_chain without TLS config");
608 "ssl_cert_chain requires both ssl_cert and ssl_key"));
623 Env const env(*
this, std::move(cfg));
624 fail(
"Should have thrown exception for ssl_cert_chain with only ssl_cert");
630 BEAST_EXPECT(
std::string(e.
what()).contains(
"Incomplete TLS configuration"));
638 testcase(
"GRPCServer with ssl_cert_chain for intermediate CA certificates");
646 getServerCertPath().
string(),
647 getServerKeyPath().
string(),
648 getCACertPath().
string());
649 Env env(*
this, std::move(cfg));
652 auto const grpcPort =
654 BEAST_EXPECT(grpcPort.has_value());
656 BEAST_EXPECT(*grpcPort > 0);
658 auto const serverAddress =
"localhost:" +
std::to_string(*grpcPort);
662 grpc::SslCredentialsOptions sslOpts;
663 sslOpts.pem_root_certs =
std::string(kCaCertContent);
664 auto tlsStub = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
665 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOpts)));
669 auto insecureStub = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
670 grpc::CreateChannel(serverAddress, grpc::InsecureChannelCredentials()));
677 testcase(
"GRPCServer with invalid/non-existent certificate file");
687 Env env(*
this, std::move(cfg));
690 auto const grpcPort =
692 BEAST_EXPECT(grpcPort.has_value());
693 BEAST_EXPECT(*grpcPort == 0);
699 testcase(
"GRPCServer with invalid/non-existent key file");
709 Env env(*
this, std::move(cfg));
712 auto const grpcPort =
714 BEAST_EXPECT(grpcPort.has_value());
715 BEAST_EXPECT(*grpcPort == 0);
721 testcase(
"GRPCServer with invalid/non-existent cert chain file");
732 Env env(*
this, std::move(cfg));
735 auto const grpcPort =
737 BEAST_EXPECT(grpcPort.has_value());
738 BEAST_EXPECT(*grpcPort == 0);
744 testcase(
"GRPCServer with invalid/non-existent client CA file");
755 Env env(*
this, std::move(cfg));
758 auto const grpcPort =
760 BEAST_EXPECT(grpcPort.has_value());
761 BEAST_EXPECT(*grpcPort == 0);
767 testcase(
"GRPCServer with empty client CA file");
772 auto emptyCAPath = getTempDir() /
"empty_ca.pem";
783 Env env(*
this, std::move(cfg));
786 auto const grpcPort =
788 BEAST_EXPECT(grpcPort.has_value());
789 BEAST_EXPECT(*grpcPort == 0);
795 testcase(
"GRPCServer with both cert chain and client CA (full mTLS with intermediates)");
809 Env env(*
this, std::move(cfg));
812 auto const grpcPort =
814 BEAST_EXPECT(grpcPort.has_value());
816 BEAST_EXPECT(*grpcPort > 0);
818 auto const serverAddress =
"localhost:" +
std::to_string(*grpcPort);
822 grpc::SslCredentialsOptions sslOptsNoClient;
823 sslOptsNoClient.pem_root_certs =
std::string(kCaCertContent);
824 auto tlsStubNoClient = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
825 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOptsNoClient)));
829 grpc::SslCredentialsOptions sslOptsWithClient;
830 sslOptsWithClient.pem_root_certs =
std::string(kCaCertContent);
831 sslOptsWithClient.pem_cert_chain =
std::string(kClientCertContent);
832 sslOptsWithClient.pem_private_key =
std::string(kClientKeyContent);
833 auto tlsStubWithClient = org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(
834 grpc::CreateChannel(serverAddress, grpc::SslCredentials(sslOptsWithClient)));
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
virtual Config & config()=0
void testWithEmptyClientCAFile()
void testWithClientCAButNoTLS()
void testWithInvalidClientCAFile()
void testWithInvalidCertChainFile()
void run() override
Runs the suite.
void testWithBothCertChainAndClientCA()
void testWithInvalidKeyFile()
void testWithMissingKey()
void testWithCertChainButNoTLS()
void testWithInvalidCertFile()
void testWithMissingCert()
A transaction testing environment.
T create_directories(T... args)
std::unique_ptr< Config > addGrpcConfigWithTLSAndCertChain(std::unique_ptr< Config >, std::string const &certPath, std::string const &keyPath, std::string const &certChainPath)
add a grpc address, port and TLS with server cert chain to config
std::unique_ptr< Config > addGrpcConfigWithTLSAndClientCA(std::unique_ptr< Config >, std::string const &certPath, std::string const &keyPath, std::string const &clientCAPath)
add a grpc address, port and TLS certificate/key/client CA paths to config
std::unique_ptr< Config > addGrpcConfigWithTLS(std::unique_ptr< Config >, std::string const &certPath, std::string const &keyPath)
add a grpc address, port and TLS certificate/key paths to config
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
std::unique_ptr< Config > addGrpcConfig(std::unique_ptr< Config >)
add a grpc address and port to config
bool makeTestGRPCCall(std::unique_ptr< org::xrpl::rpc::v1::XRPLedgerAPIService::Stub > const &stub)
Helper function to make a simple gRPC call to test connectivity.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
char const * getEnvLocalhostAddr()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static constexpr auto kSslCertChain
static constexpr auto kSslKey
static constexpr auto kPort
static constexpr auto kSslClientCa
static constexpr auto kSslCert
static constexpr auto kIp
static constexpr auto kPortGrpc
T temp_directory_path(T... args)