forked from trustwallet/wallet-core
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSigner.cpp
More file actions
113 lines (101 loc) · 4.75 KB
/
Copy pathSigner.cpp
File metadata and controls
113 lines (101 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright © 2017-2020 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.
#include "Signer.h"
#include <TrezorCrypto/ed25519.h>
#include <algorithm>
using namespace TW;
using namespace TW::Solana;
void Signer::sign(const std::vector<PrivateKey>& privateKeys, Transaction& transaction) {
for (auto privateKey : privateKeys) {
auto address = Address(privateKey.getPublicKey(TWPublicKeyTypeED25519));
auto index = transaction.getAccountIndex(address);
auto message = transaction.messageData();
auto signature = Signature(privateKey.sign(message, TWCurveED25519));
transaction.signatures[index] = signature;
}
}
Proto::SigningOutput Signer::signProtobuf(const Proto::SigningInput& input) {
auto blockhash = Solana::Hash(input.recent_blockhash());
auto key = PrivateKey(input.private_key());
Message message;
std::string stakePubkey;
std::vector<PrivateKey> signerKeys;
if (input.has_transfer_transaction()) {
auto protoMessage = input.transfer_transaction();
message = Message(
/* from */ Address(key.getPublicKey(TWPublicKeyTypeED25519)),
/* to */ Address(protoMessage.recipient()),
/* value */ protoMessage.value(),
/* recent_blockhash */ blockhash);
signerKeys.push_back(key);
} else if (input.has_stake_transaction()) {
auto protoMessage = input.stake_transaction();
auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
auto validatorAddress = Address(protoMessage.validator_pubkey());
auto stakeProgramId = Address(STAKE_ADDRESS);
auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
message = Message(
/* signer */ userAddress,
/* stakeAddress */ stakeAddress,
/* voteAddress */ validatorAddress,
/* value */ protoMessage.value(),
/* recent_blockhash */ blockhash);
signerKeys.push_back(key);
} else if (input.has_deactivate_stake_transaction()) {
auto protoMessage = input.deactivate_stake_transaction();
auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
auto validatorAddress = Address(protoMessage.validator_pubkey());
auto stakeProgramId = Address(STAKE_ADDRESS);
auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
message = Message(
/* signer */ userAddress,
/* stakeAddress */ stakeAddress,
/* type */ Deactivate,
/* recent_blockhash */ blockhash);
signerKeys.push_back(key);
} else if (input.has_withdraw_transaction()) {
auto protoMessage = input.withdraw_transaction();
auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
auto validatorAddress = Address(protoMessage.validator_pubkey());
auto stakeProgramId = Address(STAKE_ADDRESS);
auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
message = Message(
/* signer */ userAddress,
/* stakeAddress */ stakeAddress,
/* value */ protoMessage.value(),
/* type */ Withdraw,
/* recent_blockhash */ blockhash);
signerKeys.push_back(key);
}
auto transaction = Transaction(message);
sign(signerKeys, transaction);
auto protoOutput = Proto::SigningOutput();
auto encoded = transaction.serialize();
protoOutput.set_encoded(encoded.data(), encoded.size());
return protoOutput;
}
void Signer::signUpdateBlockhash(const std::vector<PrivateKey>& privateKeys,
Transaction& transaction, Solana::Hash& recentBlockhash) {
transaction.message.recentBlockhash = recentBlockhash;
Signer::sign(privateKeys, transaction);
}
// This method does not confirm that PrivateKey order matches that encoded in the messageData
// That order must be correct for the Transaction to succeed on Solana
Data Signer::signRawMessage(const std::vector<PrivateKey>& privateKeys, const Data messageData) {
std::vector<Signature> signatures;
for (auto privateKey : privateKeys) {
auto signature = Signature(privateKey.sign(messageData, TWCurveED25519));
signatures.push_back(signature);
}
Data buffer;
append(buffer, shortVecLength<Signature>(signatures));
for (auto signature : signatures) {
Data signature_vec(signature.bytes.begin(), signature.bytes.end());
append(buffer, signature_vec);
}
append(buffer, messageData);
return buffer;
}