update to 0.4 preview
[novacoin.git] / src / qt / signverifymessagedialog.cpp
1 #include "signverifymessagedialog.h"
2 #include "ui_signverifymessagedialog.h"
3
4 #include "addressbookpage.h"
5 #include "base58.h"
6 #include "guiutil.h"
7 #include "init.h"
8 #include "main.h"
9 #include "optionsmodel.h"
10 #include "walletmodel.h"
11 #include "wallet.h"
12
13 #include <string>
14 #include <vector>
15
16 #include <QClipboard>
17
18 SignVerifyMessageDialog::SignVerifyMessageDialog(QWidget *parent) :
19     QDialog(parent),
20     ui(new Ui::SignVerifyMessageDialog),
21     model(0)
22 {
23     ui->setupUi(this);
24
25 #if (QT_VERSION >= 0x040700)
26     /* Do not move this to the XML file, Qt before 4.7 will choke on it */
27     ui->addressIn_SM->setPlaceholderText(tr("Enter a NovaCoin address (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)"));
28     ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
29
30     ui->addressIn_VM->setPlaceholderText(tr("Enter a NovaCoin address (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)"));
31     ui->signatureIn_VM->setPlaceholderText(tr("Enter NovaCoin signature"));
32 #endif
33
34     GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
35     GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
36
37     ui->addressIn_SM->installEventFilter(this);
38     ui->messageIn_SM->installEventFilter(this);
39     ui->signatureOut_SM->installEventFilter(this);
40     ui->addressIn_VM->installEventFilter(this);
41     ui->messageIn_VM->installEventFilter(this);
42     ui->signatureIn_VM->installEventFilter(this);
43
44     ui->signatureOut_SM->setFont(GUIUtil::bitcoinAddressFont());
45     ui->signatureIn_VM->setFont(GUIUtil::bitcoinAddressFont());
46 }
47
48 SignVerifyMessageDialog::~SignVerifyMessageDialog()
49 {
50     delete ui;
51 }
52
53 void SignVerifyMessageDialog::setModel(WalletModel *model)
54 {
55     this->model = model;
56 }
57
58 void SignVerifyMessageDialog::setAddress_SM(QString address)
59 {
60     ui->addressIn_SM->setText(address);
61     ui->messageIn_SM->setFocus();
62 }
63
64 void SignVerifyMessageDialog::setAddress_VM(QString address)
65 {
66     ui->addressIn_VM->setText(address);
67     ui->messageIn_VM->setFocus();
68 }
69
70 void SignVerifyMessageDialog::showTab_SM(bool fShow)
71 {
72     ui->tabWidget->setCurrentIndex(0);
73
74     if (fShow)
75         this->show();
76 }
77
78 void SignVerifyMessageDialog::showTab_VM(bool fShow)
79 {
80     ui->tabWidget->setCurrentIndex(1);
81     if (fShow)
82         this->show();
83 }
84
85 void SignVerifyMessageDialog::on_addressBookButton_SM_clicked()
86 {
87     if (model && model->getAddressTableModel())
88     {
89         AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::ReceivingTab, this);
90         dlg.setModel(model->getAddressTableModel());
91         if (dlg.exec())
92         {
93             setAddress_SM(dlg.getReturnValue());
94         }
95     }
96 }
97
98 void SignVerifyMessageDialog::on_pasteButton_SM_clicked()
99 {
100     setAddress_SM(QApplication::clipboard()->text());
101 }
102
103 void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
104 {
105     /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
106     ui->signatureOut_SM->clear();
107
108     CBitcoinAddress addr(ui->addressIn_SM->text().toStdString());
109     if (!addr.IsValid())
110     {
111         ui->addressIn_SM->setValid(false);
112         ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
113         ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
114         return;
115     }
116     CKeyID keyID;
117     if (!addr.GetKeyID(keyID))
118     {
119         ui->addressIn_SM->setValid(false);
120         ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
121         ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
122         return;
123     }
124
125     WalletModel::UnlockContext ctx(model->requestUnlock());
126     if (!ctx.isValid())
127     {
128         ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
129         ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
130         return;
131     }
132
133     CKey key;
134     if (!pwalletMain->GetKey(keyID, key))
135     {
136         ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
137         ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
138         return;
139     }
140
141     CDataStream ss(SER_GETHASH, 0);
142     ss << strMessageMagic;
143     ss << ui->messageIn_SM->document()->toPlainText().toStdString();
144
145     std::vector<unsigned char> vchSig;
146     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
147     {
148         ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
149         ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
150         return;
151     }
152
153     ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
154     ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
155
156     ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size())));
157 }
158
159 void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked()
160 {
161     QApplication::clipboard()->setText(ui->signatureOut_SM->text());
162 }
163
164 void SignVerifyMessageDialog::on_clearButton_SM_clicked()
165 {
166     ui->addressIn_SM->clear();
167     ui->messageIn_SM->clear();
168     ui->signatureOut_SM->clear();
169     ui->statusLabel_SM->clear();
170
171     ui->addressIn_SM->setFocus();
172 }
173
174 void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
175 {
176     if (model && model->getAddressTableModel())
177     {
178         AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
179         dlg.setModel(model->getAddressTableModel());
180         if (dlg.exec())
181         {
182             setAddress_VM(dlg.getReturnValue());
183         }
184     }
185 }
186
187 void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
188 {
189     CBitcoinAddress addr(ui->addressIn_VM->text().toStdString());
190     if (!addr.IsValid())
191     {
192         ui->addressIn_VM->setValid(false);
193         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
194         ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
195         return;
196     }
197     CKeyID keyID;
198     if (!addr.GetKeyID(keyID))
199     {
200         ui->addressIn_VM->setValid(false);
201         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
202         ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
203         return;
204     }
205
206     bool fInvalid = false;
207     std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid);
208
209     if (fInvalid)
210     {
211         ui->signatureIn_VM->setValid(false);
212         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
213         ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
214         return;
215     }
216
217     CDataStream ss(SER_GETHASH, 0);
218     ss << strMessageMagic;
219     ss << ui->messageIn_VM->document()->toPlainText().toStdString();
220
221     CKey key;
222     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
223     {
224         ui->signatureIn_VM->setValid(false);
225         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
226         ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again."));
227         return;
228     }
229
230     if (!(CBitcoinAddress(key.GetPubKey().GetID()) == addr))
231     {
232         ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
233         ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
234         return;
235     }
236
237     ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
238     ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
239 }
240
241 void SignVerifyMessageDialog::on_clearButton_VM_clicked()
242 {
243     ui->addressIn_VM->clear();
244     ui->signatureIn_VM->clear();
245     ui->messageIn_VM->clear();
246     ui->statusLabel_VM->clear();
247
248     ui->addressIn_VM->setFocus();
249 }
250
251 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
252 {
253     if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
254     {
255         if (ui->tabWidget->currentIndex() == 0)
256         {
257             /* Clear status message on focus change */
258             ui->statusLabel_SM->clear();
259
260             /* Select generated signature */
261             if (object == ui->signatureOut_SM)
262             {
263                 ui->signatureOut_SM->selectAll();
264                 return true;
265             }
266         }
267         else if (ui->tabWidget->currentIndex() == 1)
268         {
269             /* Clear status message on focus change */
270             ui->statusLabel_VM->clear();
271         }
272     }
273     return QDialog::eventFilter(object, event);
274 }