rippled
PayChanClaim.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 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/main/Application.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <ripple/ledger/ReadView.h>
23 #include <ripple/net/RPCErr.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/PayChan.h>
26 #include <ripple/protocol/STAccount.h>
27 #include <ripple/protocol/jss.h>
28 #include <ripple/resource/Fees.h>
29 #include <ripple/rpc/Context.h>
30 #include <ripple/rpc/impl/RPCHelpers.h>
31 #include <ripple/rpc/impl/Tuning.h>
32 
33 #include <optional>
34 
35 namespace ripple {
36 
37 // {
38 // secret_key: <signing_secret_key>
39 // key_type: optional; either ed25519 or secp256k1 (default to secp256k1)
40 // channel_id: 256-bit channel id
41 // drops: 64-bit uint (as string)
42 // }
45 {
46  auto const& params(context.params);
47  for (auto const& p : {jss::channel_id, jss::amount})
48  if (!params.isMember(p))
49  return RPC::missing_field_error(p);
50 
51  // Compatibility if a key type isn't specified. If it is, the
52  // keypairForSignature code will validate parameters and return
53  // the appropriate error.
54  if (!params.isMember(jss::key_type) && !params.isMember(jss::secret))
55  return RPC::missing_field_error(jss::secret);
56 
57  Json::Value result;
58  auto const [pk, sk] =
59  RPC::keypairForSignature(params, result, context.apiVersion);
60  if (RPC::contains_error(result))
61  return result;
62 
63  uint256 channelId;
64  if (!channelId.parseHex(params[jss::channel_id].asString()))
66 
67  std::optional<std::uint64_t> const optDrops = params[jss::amount].isString()
68  ? to_uint64(params[jss::amount].asString())
69  : std::nullopt;
70 
71  if (!optDrops)
73 
74  std::uint64_t const drops = *optDrops;
75 
76  Serializer msg;
77  serializePayChanAuthorization(msg, channelId, XRPAmount(drops));
78 
79  try
80  {
81  auto const buf = sign(pk, sk, msg.slice());
82  result[jss::signature] = strHex(buf);
83  }
84  catch (std::exception const& ex)
85  {
86  result = RPC::make_error(
88  "Exception occurred during signing: " + std::string(ex.what()));
89  }
90  return result;
91 }
92 
93 // {
94 // public_key: <public_key>
95 // channel_id: 256-bit channel id
96 // drops: 64-bit uint (as string)
97 // signature: signature to verify
98 // }
101 {
102  auto const& params(context.params);
103  for (auto const& p :
104  {jss::public_key, jss::channel_id, jss::amount, jss::signature})
105  if (!params.isMember(p))
106  return RPC::missing_field_error(p);
107 
109  {
110  std::string const strPk = params[jss::public_key].asString();
111  pk = parseBase58<PublicKey>(TokenType::AccountPublic, strPk);
112 
113  if (!pk)
114  {
115  auto pkHex = strUnHex(strPk);
116  if (!pkHex)
118  auto const pkType = publicKeyType(makeSlice(*pkHex));
119  if (!pkType)
121  pk.emplace(makeSlice(*pkHex));
122  }
123  }
124 
125  uint256 channelId;
126  if (!channelId.parseHex(params[jss::channel_id].asString()))
128 
129  std::optional<std::uint64_t> const optDrops = params[jss::amount].isString()
130  ? to_uint64(params[jss::amount].asString())
131  : std::nullopt;
132 
133  if (!optDrops)
135 
136  std::uint64_t const drops = *optDrops;
137 
138  auto sig = strUnHex(params[jss::signature].asString());
139  if (!sig || !sig->size())
140  return rpcError(rpcINVALID_PARAMS);
141 
142  Serializer msg;
143  serializePayChanAuthorization(msg, channelId, XRPAmount(drops));
144 
145  Json::Value result;
146  result[jss::signature_verified] =
147  verify(*pk, msg.slice(), makeSlice(*sig), /*canonical*/ true);
148  return result;
149 }
150 
151 } // namespace ripple
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
std::string
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
std::exception
STL class.
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a signature on a message.
Definition: PublicKey.cpp:272
std::optional::emplace
T emplace(T... args)
ripple::doChannelVerify
Json::Value doChannelVerify(RPC::JsonContext &)
Definition: PayChanClaim.cpp:100
ripple::serializePayChanAuthorization
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
Definition: protocol/PayChan.h:31
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:264
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:207
ripple::base_uint< 256 >
ripple::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error, unsigned int apiVersion)
Definition: RPCHelpers.cpp:796
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:196
ripple::doChannelAuthorize
Json::Value doChannelAuthorize(RPC::JsonContext &)
Definition: PayChanClaim.cpp:44
ripple::to_uint64
std::optional< std::uint64_t > to_uint64(std::string const &s)
ripple::rpcPUBLIC_MALFORMED
@ rpcPUBLIC_MALFORMED
Definition: ErrorCodes.h:117
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:64
std::uint64_t
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:130
ripple::rpcCHANNEL_AMT_MALFORMED
@ rpcCHANNEL_AMT_MALFORMED
Definition: ErrorCodes.h:101
ripple::Serializer
Definition: Serializer.h:40
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sign
Buffer sign(PublicKey const &pk, SecretKey const &sk, Slice const &m)
Generate a signature for a message.
Definition: SecretKey.cpp:238
ripple::RPC::Context::apiVersion
unsigned int apiVersion
Definition: Context.h:50
ripple::TokenType::AccountPublic
@ AccountPublic
ripple::rpcCHANNEL_MALFORMED
@ rpcCHANNEL_MALFORMED
Definition: ErrorCodes.h:100
optional
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:52
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:180
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46