1
// Copyright © 2017-2020 Trust Wallet.
2
//
3
// This file is part of Trust. The full Trust copyright notice, including
4
// terms governing use, modification, and redistribution, is contained in the
5
// file LICENSE at the root of the source code distribution tree.
6

7
#include "Signer.h"
8
#include "../Base58.h"
9
#include <TrezorCrypto/ed25519.h>
10

11
#include <algorithm>
12

13
using namespace TW;
14
using namespace TW::Solana;
15

16 1
void Signer::sign(const std::vector<PrivateKey>& privateKeys, Transaction& transaction) {
17 1
    for (auto privateKey : privateKeys) {
18 1
        auto address = Address(privateKey.getPublicKey(TWPublicKeyTypeED25519));
19 1
        auto index = transaction.getAccountIndex(address);
20 1
        auto message = transaction.messageData();
21 1
        auto signature = Signature(privateKey.sign(message, TWCurveED25519));
22 1
        transaction.signatures[index] = signature;
23
    }
24
}
25

26 1
Proto::SigningOutput Signer::sign(const Proto::SigningInput& input) noexcept {
27 1
    auto blockhash = Solana::Hash(input.recent_blockhash());
28 1
    auto key = PrivateKey(Data(input.private_key().begin(), input.private_key().end()));
29 1
    Message message;
30 1
    std::string stakePubkey;
31 1
    std::vector<PrivateKey> signerKeys;
32

33 1
    if (input.has_transfer_transaction()) {
34 1
        auto protoMessage = input.transfer_transaction();
35 1
        message = Message(
36 1
            /* from */ Address(key.getPublicKey(TWPublicKeyTypeED25519)),
37 1
            /* to */ Address(protoMessage.recipient()),
38 1
            /* value */ protoMessage.value(),
39 1
            /* recent_blockhash */ blockhash);
40 1
        signerKeys.push_back(key);
41 1
    } else if (input.has_stake_transaction()) {
42 1
        auto protoMessage = input.stake_transaction();
43 1
        auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
44 1
        auto validatorAddress = Address(protoMessage.validator_pubkey());
45 1
        auto stakeProgramId = Address(STAKE_ADDRESS);
46 1
        auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
47 1
        message = Message(
48 1
            /* signer */ userAddress,
49 1
            /* stakeAddress */ stakeAddress,
50 1
            /* voteAddress */ validatorAddress,
51 1
            /* value */ protoMessage.value(),
52 1
            /* recent_blockhash */ blockhash);
53 1
        signerKeys.push_back(key);
54 1
    } else if (input.has_deactivate_stake_transaction()) {
55 1
        auto protoMessage = input.deactivate_stake_transaction();
56 1
        auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
57 1
        auto validatorAddress = Address(protoMessage.validator_pubkey());
58 1
        auto stakeProgramId = Address(STAKE_ADDRESS);
59 1
        auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
60 1
        message = Message(
61 1
            /* signer */ userAddress,
62 1
            /* stakeAddress */ stakeAddress,
63
            /* type */ Deactivate,
64 1
            /* recent_blockhash */ blockhash);
65 1
        signerKeys.push_back(key);
66 1
    } else if (input.has_withdraw_transaction()) {
67 1
        auto protoMessage = input.withdraw_transaction();
68 1
        auto userAddress = Address(key.getPublicKey(TWPublicKeyTypeED25519));
69 1
        auto validatorAddress = Address(protoMessage.validator_pubkey());
70 1
        auto stakeProgramId = Address(STAKE_ADDRESS);
71 1
        auto stakeAddress = addressFromValidatorSeed(userAddress, validatorAddress, stakeProgramId);
72 1
        message = Message(
73 1
            /* signer */ userAddress,
74 1
            /* stakeAddress */ stakeAddress,
75 1
            /* value */ protoMessage.value(),
76
            /* type */ Withdraw,
77 1
            /* recent_blockhash */ blockhash);
78 1
        signerKeys.push_back(key);
79
    }
80 1
    auto transaction = Transaction(message);
81

82 1
    sign(signerKeys, transaction);
83

84 1
    auto protoOutput = Proto::SigningOutput();
85 1
    auto encoded = transaction.serialize();
86 1
    protoOutput.set_encoded(encoded);
87

88 1
    return protoOutput;
89
}
90

91 1
void Signer::signUpdateBlockhash(const std::vector<PrivateKey>& privateKeys,
92
                                 Transaction& transaction, Solana::Hash& recentBlockhash) {
93 1
    transaction.message.recentBlockhash = recentBlockhash;
94 1
    Signer::sign(privateKeys, transaction);
95
}
96

97
// This method does not confirm that PrivateKey order matches that encoded in the messageData
98
// That order must be correct for the Transaction to succeed on Solana
99 1
Data Signer::signRawMessage(const std::vector<PrivateKey>& privateKeys, const Data messageData) {
100 1
    std::vector<Signature> signatures;
101 1
    for (auto privateKey : privateKeys) {
102 1
        auto signature = Signature(privateKey.sign(messageData, TWCurveED25519));
103 1
        signatures.push_back(signature);
104
    }
105 1
    Data buffer;
106 1
    append(buffer, shortVecLength<Signature>(signatures));
107 1
    for (auto signature : signatures) {
108 1
        Data signature_vec(signature.bytes.begin(), signature.bytes.end());
109 1
        append(buffer, signature_vec);
110
    }
111 1
    append(buffer, messageData);
112

113 1
    return buffer;
114
}

Read our documentation on viewing source code .

Loading