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] = RPC::keypairForSignature(params, result);
59  if (RPC::contains_error(result))
60  return result;
61 
62  uint256 channelId;
63  if (!channelId.parseHex(params[jss::channel_id].asString()))
65 
66  std::optional<std::uint64_t> const optDrops = params[jss::amount].isString()
67  ? to_uint64(params[jss::amount].asString())
68  : std::nullopt;
69 
70  if (!optDrops)
72 
73  std::uint64_t const drops = *optDrops;
74 
75  Serializer msg;
76  serializePayChanAuthorization(msg, channelId, XRPAmount(drops));
77 
78  try
79  {
80  auto const buf = sign(pk, sk, msg.slice());
81  result[jss::signature] = strHex(buf);
82  }
83  catch (std::exception&)
84  {
85  result =
86  RPC::make_error(rpcINTERNAL, "Exception occurred during signing.");
87  }
88  return result;
89 }
90 
91 // {
92 // public_key: <public_key>
93 // channel_id: 256-bit channel id
94 // drops: 64-bit uint (as string)
95 // signature: signature to verify
96 // }
99 {
100  auto const& params(context.params);
101  for (auto const& p :
102  {jss::public_key, jss::channel_id, jss::amount, jss::signature})
103  if (!params.isMember(p))
104  return RPC::missing_field_error(p);
105 
107  {
108  std::string const strPk = params[jss::public_key].asString();
109  pk = parseBase58<PublicKey>(TokenType::AccountPublic, strPk);
110 
111  if (!pk)
112  {
113  auto pkHex = strUnHex(strPk);
114  if (!pkHex)
116  auto const pkType = publicKeyType(makeSlice(*pkHex));
117  if (!pkType)
119  pk.emplace(makeSlice(*pkHex));
120  }
121  }
122 
123  uint256 channelId;
124  if (!channelId.parseHex(params[jss::channel_id].asString()))
126 
127  std::optional<std::uint64_t> const optDrops = params[jss::amount].isString()
128  ? to_uint64(params[jss::amount].asString())
129  : std::nullopt;
130 
131  if (!optDrops)
133 
134  std::uint64_t const drops = *optDrops;
135 
136  auto sig = strUnHex(params[jss::signature].asString());
137  if (!sig || !sig->size())
138  return rpcError(rpcINVALID_PARAMS);
139 
140  Serializer msg;
141  serializePayChanAuthorization(msg, channelId, XRPAmount(drops));
142 
143  Json::Value result;
144  result[jss::signature_verified] =
145  verify(*pk, msg.slice(), makeSlice(*sig), /*canonical*/ true);
146  return result;
147 }
148 
149 } // 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:98
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:262
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:207
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:194
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:63
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:39
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::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:751
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:495
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:50
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:178
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46