diff --git a/.svn/pristine/01/016bf7c6d4d408fc5bc88abc77ad31377dcd6242.svn-base b/.svn/pristine/01/016bf7c6d4d408fc5bc88abc77ad31377dcd6242.svn-base
new file mode 100644
index 0000000..2726a4a
--- /dev/null
+++ b/.svn/pristine/01/016bf7c6d4d408fc5bc88abc77ad31377dcd6242.svn-base
@@ -0,0 +1,449 @@
+
+
+ RecvHistory
+
+
+
+ 0
+ 0
+ 780
+ 628
+
+
+
+ Form
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 191
+
+
+
+
+ 16777215
+ 191
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
-
+
+
+ 7
+
+
-
+
+
+
+ 41
+ 41
+
+
+
+
+ 41
+ 41
+
+
+
+ background-image: url(:/res/png/recvicon.png);border:none
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 76
+
+
+
+
+ 16777215
+ 76
+
+
+
+
+
+
+
+
+
+ IsRecv
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 82
+
+
+
+
+ 16777215
+ 82
+
+
+
+
-
+
+
+
+ 13
+
+
+
+ background-color: rgb(242, 241, 240);
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
-
+
+
-
+
+
+
+
+
+
+
+
+ add
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ TextLabel
+
+
+ Qt::TextSelectableByMouse
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+
+
+
+
+
+ date
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ TextLabel
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+
+
+ info
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ TextLabel
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.svn/pristine/05/05aa8408d84de79c9d0b0ff613082eff5a8d9951.svn-base b/.svn/pristine/05/05aa8408d84de79c9d0b0ff613082eff5a8d9951.svn-base
new file mode 100644
index 0000000..ad33022
--- /dev/null
+++ b/.svn/pristine/05/05aa8408d84de79c9d0b0ff613082eff5a8d9951.svn-base
@@ -0,0 +1,33 @@
+#ifndef UNIONACCOUNTJOIN_H
+#define UNIONACCOUNTJOIN_H
+
+#include
+#include "wallet/wallet.h"
+class WalletModel;
+namespace Ui {
+class unionaccountjoin;
+}
+
+class unionaccountjoin : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit unionaccountjoin(QWidget *parent = 0);
+ ~unionaccountjoin();
+ void setModel(WalletModel *_model);
+ void showEvent(QShowEvent *event);
+Q_SIGNALS:
+ void opensuccessjoinPage();
+ void refreshunionaccount();
+private Q_SLOTS:
+ void on_joinBtn_pressed();
+
+ void on_btn_import_pressed();
+
+private:
+ Ui::unionaccountjoin *ui;
+ WalletModel *model;
+};
+
+#endif // UNIONACCOUNTJOIN_H
diff --git a/.svn/pristine/05/05fdd60e66b371ea92a4ad9b39ee4842fa4dcf8c.svn-base b/.svn/pristine/05/05fdd60e66b371ea92a4ad9b39ee4842fa4dcf8c.svn-base
new file mode 100644
index 0000000..11f514a
Binary files /dev/null and b/.svn/pristine/05/05fdd60e66b371ea92a4ad9b39ee4842fa4dcf8c.svn-base differ
diff --git a/.svn/pristine/08/08bb7715e2d9941c74554230bbb79a6326cad2bc.svn-base b/.svn/pristine/08/08bb7715e2d9941c74554230bbb79a6326cad2bc.svn-base
new file mode 100644
index 0000000..f4352f1
--- /dev/null
+++ b/.svn/pristine/08/08bb7715e2d9941c74554230bbb79a6326cad2bc.svn-base
@@ -0,0 +1,54 @@
+#ifndef UNIONACCOUNTHISTORY_H
+#define UNIONACCOUNTHISTORY_H
+#include
+#include
+#include "wallet/wallet.h"
+class WalletModel;
+class CWalletTx;
+namespace Ui {
+class unionaccounthistory;
+}
+struct tra_info{
+ bool isSend;
+ std::string add;
+ CAmount num;
+ CAmount fee;
+ QString status;
+ QString strtime ;
+ QString txid;
+};
+class unionaccounthistory : public QWidget
+{
+ Q_OBJECT
+
+public:
+ unionaccounthistory(QWidget *parent = 0);
+ ~unionaccounthistory();
+ void updateinfo(std::map s);
+ void setAdd(std::string add);
+ void setnum(CAmount num);
+ void addline();
+ void setModel(WalletModel *_model);
+ Q_SIGNALS:
+ void backtoTraPage();
+ void jumptohistorysend(std::string add, CAmount fee,bool isSend,CAmount num,QString status,QString strtime,QString txid);
+ void jumptohistoryrecv(std::string add, CAmount fee,bool isSend,CAmount num,QString status,QString strtime,QString txid);
+
+private Q_SLOTS:
+ void on_btn_back_pressed();
+ void lookupinfodetail(std::string add, bool isSend,QString status,
+ QString strtime,CAmount s,CAmount s1,QString txid);
+private:
+ std::string getAdd();
+ void addinfo(std::string add, CAmount fee,bool isSend,
+ CAmount num,QString status,QString strtime,QString txid);
+ CAmount getnum();
+ Ui::unionaccounthistory *ui;
+ std::string m_add;
+ CAmount m_num;
+ QVBoxLayout * pvboxlayoutall;
+ WalletModel * m_pwalletmodel;
+ std::vector m_tra;
+};
+
+#endif // UNIONACCOUNTHISTORY_H
diff --git a/.svn/pristine/0d/0d896f268b09a09b84e8f5b3ced269a8ecdbeb3d.svn-base b/.svn/pristine/0d/0d896f268b09a09b84e8f5b3ced269a8ecdbeb3d.svn-base
new file mode 100644
index 0000000..b04b44e
--- /dev/null
+++ b/.svn/pristine/0d/0d896f268b09a09b84e8f5b3ced269a8ecdbeb3d.svn-base
@@ -0,0 +1,57 @@
+#ifndef WALLETPAGEBUTTONS_H
+#define WALLETPAGEBUTTONS_H
+
+#include
+#include
+class CMessageBox;
+namespace Ui {
+class walletpagebuttons;
+}
+
+class walletpagebuttons : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit walletpagebuttons(QWidget *parent = 0);
+ ~walletpagebuttons();
+
+ void fresh(int concount,int count);
+
+private Q_SLOTS:
+ void on_pushButton_set_pressed();
+ void on_pushButton_setpic_pressed();
+ void on_pushButton_ipc_pressed();
+ void on_pushButton_ipcpic_pressed();
+ void on_pushButton_recive_pressed();
+ void on_pushButton_recivepic_pressed();
+ void on_pushButton_send_pressed();
+ void on_pushButton_sendpic_pressed();
+ void on_pushButton_wallet_pressed();
+ //void on_pushButton_walletpic_pressed();
+ void getWalletPageButtonsStatus();
+ void on_pushButton_markbill_pressed();
+
+ void on_pushButton_eipc_pressed();
+
+ void on_pushButton_unionaccount_pressed();
+
+Q_SIGNALS:
+ void setpressed();
+ void ipcpressed();
+ void recivepressed();
+ void sendpressed();
+ void walletpressed();
+ void tallypressed();
+ void eipcpressed();
+ void unionpressed();
+private:
+ Ui::walletpagebuttons *ui;
+ void setpushbuttonchecked(QString name,QPushButton* wallet,\
+ QString graypicname,QString greenpicname);
+ void setMsgDlgPlace(CMessageBox*);
+ QString formatLang() ;
+ bool is_uniond;
+};
+
+#endif // WALLETPAGEBUTTONS_H
diff --git a/.svn/pristine/0e/0e736510343e20f8df65d631ae45fe6940eccd73.svn-base b/.svn/pristine/0e/0e736510343e20f8df65d631ae45fe6940eccd73.svn-base
new file mode 100644
index 0000000..b8ca763
--- /dev/null
+++ b/.svn/pristine/0e/0e736510343e20f8df65d631ae45fe6940eccd73.svn-base
@@ -0,0 +1,188 @@
+// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "sendcoinsdialog.h"
+#include "ui_sendcoinsdialog.h"
+#include "addresstablemodel.h"
+#include "ipchainunits.h"
+#include "clientmodel.h"
+#include "guiutil.h"
+#include "optionsmodel.h"
+#include "platformstyle.h"
+#include "walletmodel.h"
+#include "base58.h"
+#include "chainparams.h"
+#include "wallet/coincontrol.h"
+#include "validation.h"
+#include "ui_interface.h"
+#include "txmempool.h"
+#include "wallet/wallet.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "config/bitcoin-config.h" /* for USE_QRCODE */
+#include
+#include "log/stateinfo.h"
+
+#define SEND_CONFIRM_DELAY 3
+
+SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::SendCoinsDialog),
+ clientModel(0),
+ model(0),
+ fNewRecipientAllowed(true),
+ fFeeMinimized(true),
+ platformStyle(_platformStyle)
+{
+ ui->setupUi(this);
+ eTag =0;
+ ui->comboBox->addItem(tr("IPC"), IPC);
+ ui->comboBox->addItem(tr("mIPC"),mIPC);
+ ui->ReceiverEdit->setPlaceholderText(tr("input receiver"));
+ ui->labelEdit->setPlaceholderText(tr("input label"));
+ ui->CoinEdit->setPlaceholderText(tr("input num"));
+ QRegExp regx("^\\d+(\\.\\d+)?$");
+ QValidator *validator = new QRegExpValidator(regx, ui->CoinEdit );
+ ui->CoinEdit->setValidator( validator );
+ connect(ui->comboBox, SIGNAL(activated(int)), this, SLOT(coinUpdate(int)));
+
+}
+void SendCoinsDialog::coinUpdate(int idx)
+{
+ QDate current = QDate::currentDate();
+ switch(ui->comboBox->itemData(idx).toInt())
+ {
+ case IPC:
+ {
+ eTag = 0;
+ }
+ break;
+ case mIPC:
+ {
+ eTag = 1;
+ }
+ break;
+ case uIPC:
+ {
+ eTag = 2;
+ }
+ break;
+ case zhi:
+ {
+ eTag = 3;
+ }
+ break;
+ default:
+ {
+ eTag = 0;
+ }
+ }
+}
+void SendCoinsDialog::setClientModel(ClientModel *_clientModel)
+{
+ this->clientModel = _clientModel;
+}
+
+void SendCoinsDialog::setModel(WalletModel *_model)
+{
+ this->model = _model;
+}
+
+SendCoinsDialog::~SendCoinsDialog()
+{
+ QSettings settings;
+ delete ui;
+}
+void SendCoinsDialog::setAddress(const QString &address,const QString &label)
+{
+ ui->ReceiverEdit->setText(address);
+ ui->labelEdit->setText(label);
+}
+/*
+void SendCoinsDialog::on_scanBtn_pressed()
+{
+ QString filename = GUIUtil::getOpenFileName(this, tr("Select payment request file to open"), "", "", NULL);
+ if(filename.isEmpty())
+ return;
+ QRcode_encodeString("http://www.ipcchain.com/", 2, QR_ECLEVEL_Q, QR_MODE_8, 0);
+ QRcode *code = QRcode_encodeString("uri.toUtf8().constData()", 0, QR_ECLEVEL_L, QR_MODE_8, 1);
+ if (!code)
+ {
+ return;
+ }
+ QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
+ qrImage.fill(0xffffff);
+ unsigned char *p = code->data;
+ for (int y = 0; y < code->width; y++)
+ {
+ for (int x = 0; x < code->width; x++)
+ {
+ qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
+ p++;
+ }
+ }
+ QRcode_free(code);
+
+ QImage qrAddrImage = QImage(300, 300+20, QImage::Format_RGB32);
+ qrAddrImage.fill(0xffffff);
+
+ QPainter painter(&qrAddrImage);
+ painter.drawImage(0, 0, qrImage.scaled(300, 300));
+ QFont font = GUIUtil::fixedPitchFont();
+ font.setPixelSize(12);
+ painter.setFont(font);
+ QRect paddedRect = qrAddrImage.rect();
+ paddedRect.setHeight(300+12);
+ painter.end();
+
+}
+*/
+void SendCoinsDialog::on_AddAdsButton_pressed()
+{
+ Q_EMIT openAddBookPagewidget(2);
+}
+void SendCoinsDialog::on_GoSettingBtn_pressed()
+{
+
+ QString a = ui->ReceiverEdit->text();
+ QString label = ui->labelEdit->text();
+ QString b = ui->CoinEdit->text();
+ if(a != NULL && b != NULL)
+ {
+ if(!model->validateAddress(a))
+ {
+ ui->tiplabel->setText(tr("The recipient address is not valid. Please recheck."));
+ return;
+ }else{
+ ui->tiplabel->setText(tr(""));
+ }
+ }
+ else
+ {
+ ui->tiplabel->setText(tr("input info"));
+ return;
+ }
+ bool isCrypted = this->model->CheckIsCrypted();
+ if(isCrypted)
+ {
+
+ Q_EMIT openSendAffrimwidget(a,b,label,eTag);
+ }
+ else
+ {
+ Q_EMIT openSettingwidget(a,b,label,eTag);
+ }
+}
+void SendCoinsDialog::clearInfo()
+{
+ ui->ReceiverEdit->setText("");
+ ui->labelEdit->setText("");
+ ui->CoinEdit->setText("");
+}
diff --git a/.svn/pristine/10/10fb07ee8d1da5d6628aaa3775bf4adf1f886078.svn-base b/.svn/pristine/10/10fb07ee8d1da5d6628aaa3775bf4adf1f886078.svn-base
new file mode 100644
index 0000000..96e0f85
--- /dev/null
+++ b/.svn/pristine/10/10fb07ee8d1da5d6628aaa3775bf4adf1f886078.svn-base
@@ -0,0 +1,292 @@
+#include "unionaccounttrasend.h"
+#include "ui_unionaccounttrasend.h"
+#include "log/log.h"
+#include
+#include
+#include
+#include "intro.h"
+#ifdef WIN32
+#include
+const std::string DIRECTORY_SEPARATOR = "\\";
+#else
+const std::string DIRECTORY_SEPARATOR = "/";
+#endif
+
+#ifdef WIN32
+static void CreateDir(const std::string& path)
+{
+ CreateDirectoryA(path.c_str(), NULL);
+}
+#else
+#include
+#include
+#include
+
+#define MAX_PATH 512
+
+
+static void CreateDir(const std::string& path)
+{
+ mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+}
+
+#endif
+unionaccounttrasend::unionaccounttrasend(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::unionaccounttrasend)
+{
+ ui->setupUi(this);
+
+ QRegExp regx("^\\d+(\\.\\d+)?$");
+ QValidator *validator = new QRegExpValidator(regx, ui->lineEdit_num );
+ ui->lineEdit_num->setValidator( validator );
+}
+
+unionaccounttrasend::~unionaccounttrasend()
+{
+ delete ui;
+}
+void unionaccounttrasend::setModel(WalletModel *_model)
+{
+ this->model = _model;
+}
+void unionaccounttrasend::setaddress(QString add)
+{
+ ui->lineEdit_add->setText("");
+ ui->lineEdit_num->setText("");
+ ui->textEdit->setText("");
+ ui->label_tip->setText("");
+ m_add =add;
+}
+QString unionaccounttrasend::getaddress()
+{
+ return m_add;
+}
+void unionaccounttrasend::on_sendbtn_pressed()
+{
+
+
+ ui->label_tip->setText("");
+ m_sendcoinerror = "";
+ if(!model || !model->getOptionsModel())
+ return;
+ if("" == ui->lineEdit_num->text() ||
+ "" == ui->lineEdit_add->text())
+ {
+ ui->label_tip->setText(tr("input info"));
+ return;
+ }
+
+ if(!model->CheckPassword())
+ {
+ ui->label_tip->setText(tr("Password error."));
+ LOG_WRITE(LOG_INFO,"on_sendbtn_pressed Password error.");
+ return;
+ }
+ WalletModel::UnlockContext ctx(model, true, true);
+
+ // CAmount t = (ui->lineEdit_num->text()).toDouble();//num
+ QString t = ui->lineEdit_num->text();
+ int h= t.indexOf(" ");
+ QString s = t.mid(0,h);
+ double num = s.toDouble();
+ num=num*100000000;
+ QString add = ui->lineEdit_add->text();
+ ScriptError serror;
+ std::string strtx = "";
+ QString add_from = getaddress();
+ // LOG_WRITE(LOG_INFO,"SendMul num*00000",QString::number(num).toStdString().c_str());
+
+ WalletModel::SendCoinsReturn sendStatus =model->repreparUnionaccountCreate(add_from,add,num,serror,strtx);
+
+ LOG_WRITE(LOG_INFO,"sendStatus",QString::number(sendStatus.status).toStdString().c_str());
+ if( WalletModel::OK == sendStatus.status )
+ {
+ if(ScriptError::SCRIPT_ERR_OK == serror)
+ {
+ std::string strFailReason;
+ ScriptError serror;
+ std::string strFailReason_plus;
+ std::string strtxout;
+ CMutableTransaction mergedTx;
+ if(model->commitUnionaccounttra( strtx, strFailReason,serror,strtxout,mergedTx))
+ {
+ if(ScriptError::SCRIPT_ERR_OK == serror)
+ {
+ if(model->commitUnionaccounttra_plus(mergedTx,strFailReason_plus))
+ {
+ Q_EMIT opensendsuccessPage(tr("sign successed"),"");
+ }
+ }
+ else
+ {
+ std::string path = Intro::m_datapath;
+ if(path == "")return;
+ CreateDir(path);
+
+ std::string logFile = path +DIRECTORY_SEPARATOR+ "address.txt";
+
+ FILE* m_file = fopen(logFile.c_str(), "a+");
+
+
+ fprintf(m_file, "address: %s\n", add_from.toStdString().c_str());
+ fprintf(m_file, "script: %s\n",QString::fromStdString(strtx).toStdString().c_str() );
+
+ fclose(m_file);
+
+
+ Q_EMIT opensendsuccessPage(tr("create successed"), QString::fromStdString(strtxout));
+ }
+ }
+ else
+ {
+ LOG_WRITE(LOG_INFO,"SEND sign error");
+ ui->label_tip->setText(tr("sign error"));
+ }
+ }
+ else
+ {
+
+ std::string path = Intro::m_datapath;
+ if(path == "")return;
+ CreateDir(path);
+
+ std::string logFile = path +DIRECTORY_SEPARATOR+ "address.txt";
+/*
+ QFile file(logFile.c_str());
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ LOG_WRITE(LOG_INFO,"open fail");
+ return;
+ }
+ else
+ {
+ QString str1, str2, qstr_similarity, sumqstr;
+ for(int i = 0; i < 1; ++i)
+ {
+ str1 = QString::fromStdString(ui->textEdit->document()->toPlainText().toStdString());
+
+ sumqstr = "address:"+add_from+"\n"+"script:" + QString::fromStdString(strtx) + "\n" ;
+ }
+ QTextStream in(&file);
+ in << sumqstr;
+ file.close();
+
+ }
+ */
+ FILE* m_file = fopen(logFile.c_str(), "a+");
+
+
+ fprintf(m_file, "address: %s\n", add_from.toStdString().c_str());
+ fprintf(m_file, "script: %s\n",QString::fromStdString(strtx).toStdString().c_str() );
+ fclose(m_file);
+
+
+ Q_EMIT opensendsuccessPage(tr("create successed"), QString::fromStdString(strtx));
+
+ }
+
+ }
+ else
+ {
+
+ m_sendcoinerror = model->m_sendcoinerror;
+ LOG_WRITE(LOG_INFO,"error",m_sendcoinerror.c_str());
+ processSendCoinsReturn(sendStatus);
+ }
+
+}
+void unionaccounttrasend::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn)
+{
+ QPalette pa;
+ pa.setColor(QPalette::WindowText,Qt::black);
+
+ switch(sendCoinsReturn.status)
+ {
+ case WalletModel::PsdErr:
+ ui->label_tip->setText(tr("password error"));
+ break;
+ case WalletModel::InvalidAddress:
+ ui->label_tip->setText(tr("The recipient address is not valid. Please recheck."));
+ break;
+ case WalletModel::InvalidAmount:
+ ui->label_tip->setText(tr("Invalid Amount!"));
+ break;
+ case WalletModel::AmountExceedsBalance:
+ ui->label_tip->setText(tr("The amount exceeds your balance."));
+ break;
+ case WalletModel::AmountWithFeeExceedsBalance:
+ // ui->label_tip->setText(tr("The total exceeds your balance when the 0.001IPC/KB transaction fee is included.").arg(msgArg));
+ break;
+ case WalletModel::DuplicateAddress:
+ ui->label_tip->setText(tr("Duplicate address found: addresses should only be used once each."));
+ break;
+ case WalletModel::TransactionCreationFailed:
+ if(m_sendcoinerror!="")
+ ui->label_tip->setText(m_sendcoinerror.c_str());
+ else
+ ui->label_tip->setText(tr("Transaction creation failed!"));
+ break;
+ case WalletModel::TransactionCommitFailed:
+ {
+ if("bad-Token-tokensymbol-repeat" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-tokensymbol-repeat"));
+
+ }
+ else if("bad-Token-tokenhash-repeat" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-tokenhash-repeat"));
+
+ }
+ else if("bad-Token-Multi-inType" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-Multi-inType"));
+
+ }
+ else if("bad-Token-Reg-issueDate(Regtime)" == sendCoinsReturn.reasonCommitFailed)
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-Reg-issueDate(Regtime)"));
+
+ }
+ else if("bad-Token-regtotoken-value-unequal" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-regtotoken-value-unequal"));
+ }
+ else if("bad-Token-Label-contain-errvalue"== sendCoinsReturn.reasonCommitFailed)
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-Label-contain-errvalue"));
+ }
+ else if("bad-Token-Symbol-contain-errvalue"== sendCoinsReturn.reasonCommitFailed)
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-Symbol-contain-errvalue"));
+ }
+ else if("bad-Token-value-unequal" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-value-unequal"));
+ }
+ else if("bad-Token-Multi-outType" == sendCoinsReturn.reasonCommitFailed )
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: bad-Token-Multi-outType"));
+ }
+ else
+ {
+ ui->label_tip->setText(tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed));
+ }
+ }
+ break;
+ case WalletModel::AbsurdFee:
+ ui->label_tip->setText(tr("A fee higher is considered an absurdly high fee."));
+ break;
+ case WalletModel::PaymentRequestExpired:
+ ui->label_tip->setText(tr("Payment request expired."));
+ break;
+ case WalletModel::OK:
+ default:
+ return;
+ }
+}
+
+void unionaccounttrasend::on_pushButton_back_pressed()
+{
+ Q_EMIT backtotraPage();
+}
diff --git a/.svn/pristine/11/11023b6c4929327c658c99158dbf98c0f62ad26c.svn-base b/.svn/pristine/11/11023b6c4929327c658c99158dbf98c0f62ad26c.svn-base
new file mode 100644
index 0000000..a414e04
--- /dev/null
+++ b/.svn/pristine/11/11023b6c4929327c658c99158dbf98c0f62ad26c.svn-base
@@ -0,0 +1,154 @@
+#include "ecoinsendaffrimdialog.h"
+#include "forms/ui_ecoinsendaffrimdialog.h"
+#include "addresstablemodel.h"
+#include "optionsmodel.h"
+#include "ipchainunits.h"
+#include "wallet/coincontrol.h"
+#include "guiutil.h"
+#include
+#include "wallet/wallet.h"
+#include
+#include "log/log.h"
+#include
+#include
+#include
+
+ecoinsendaffrimdialog::ecoinsendaffrimdialog(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::ecoinsendaffrimdialog)
+{
+ ui->setupUi(this);
+}
+void ecoinsendaffrimdialog::showEvent(QShowEvent * p)
+{
+ ui->addEdit->setText("");
+ ui->numEdit->setText("");
+ ui->tiplabel->setText("");
+ ui->addEdit->setFocusPolicy(Qt::StrongFocus);
+ ui->addEdit->setFocus(Qt::OtherFocusReason);
+ ui->numEdit->clearFocus();
+}
+ecoinsendaffrimdialog::~ecoinsendaffrimdialog()
+{
+ delete ui;
+}
+void ecoinsendaffrimdialog::setModel(WalletModel *_model)
+{
+ this->model = _model;
+}
+void ecoinsendaffrimdialog::setMsg(QString name,QString num)
+{
+
+ m_name = name;
+ m_num = num;
+ std::string strname = name.toStdString();
+ int acc = model->GetAccuracyBySymbol(strname);
+ QString exp("1000000000000000000|([0-9]{0,19}[\.][0-9]{0,");
+ exp+=(QString::number(acc));
+ exp = exp + ("})");
+ QRegExp double_rx10000(exp);
+ QValidator *validator = new QRegExpValidator(double_rx10000, ui->numEdit );
+ ui->numEdit->setValidator( validator );
+ ui->tokenlabel->setText(name);
+ ui->addEdit->setText("");
+ ui->numEdit->setText("");
+ ui->tiplabel->setText("");
+ ui->numEdit->clearFocus();
+
+}
+
+void ecoinsendaffrimdialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg)
+{
+ QPalette pa;
+ pa.setColor(QPalette::WindowText,Qt::black);
+
+ LOG_WRITE(LOG_INFO,"processSendCoinsReturn","sendCoinsReturn.status",\
+ QString::number(sendCoinsReturn.status).toStdString().c_str(),\
+ "m_error",m_error.c_str());
+
+ switch(sendCoinsReturn.status)
+ {
+ case WalletModel::PsdErr:
+ ui->tiplabel->setText(tr("password error"));
+ break;
+ case WalletModel::NumErr:
+ ui->tiplabel->setText(tr("Please enter the correct amount"));
+ break;
+ case WalletModel::InvalidAddress:
+ ui->tiplabel->setText(tr("The recipient address is not valid. Please recheck."));
+ break;
+ case WalletModel::InvalidAmount:
+ ui->tiplabel->setText(tr("The amount to pay must be larger than 0."));
+ break;
+ case WalletModel::AmountExceedsBalance:
+ ui->tiplabel->setText(tr("The amount exceeds your balance."));
+ break;
+ case WalletModel::AmountWithFeeExceedsBalance:
+ ui->tiplabel->setText(tr("The total exceeds your balance."));
+ break;
+ case WalletModel::DuplicateAddress:
+ ui->tiplabel->setText(tr("Duplicate address found: addresses should only be used once each."));
+ break;
+ case WalletModel::TransactionCreationFailed:
+ if(m_error == "The tokenvalue is too big,you have not enough tokencoins.")
+ ui->tiplabel->setText(tr("The tokenvalue is too big,you have not enough tokencoins."));
+ else if(m_error == "The Tokenvalue is too big,you have not enough Tokencoins.")
+ ui->tiplabel->setText(tr("The Tokenvalue is too big,you have not enough Tokencoins."));
+ else
+ ui->tiplabel->setText(tr("Transaction creation failed!") + " " + m_error.c_str());
+ break;
+ case WalletModel::TransactionCommitFailed:
+ if(m_error == "Token-reg-starttime-is-up-yet")
+ ui->tiplabel->setText(tr("Token-reg-starttime-is-up-yet"));
+ else
+ ui->tiplabel->setText(tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed));
+ break;
+ case WalletModel::AbsurdFee:
+ ui->tiplabel->setText(tr("A fee higher"));
+ break;
+ case WalletModel::PaymentRequestExpired:
+ ui->tiplabel->setText(tr("Payment request expired."));
+ break;
+ case WalletModel::OK:
+ default:
+ return;
+ }
+}
+
+
+void ecoinsendaffrimdialog::on_sendecoinButton_pressed()
+{
+ m_error = "";
+ if(!model || !model->getOptionsModel())
+ return;
+ if("" == ui->addEdit->text() ||
+ "" == ui->numEdit->text())
+ {
+ ui->tiplabel->setText(tr("input info"));
+ return;
+ }
+ QString num = ui->numEdit->text();
+ QString pointword = ".";
+ if(num.indexOf(pointword) == num.size()-1){
+ ui->tiplabel->setText(tr("Please enter the correct amount"));
+ return;
+ }
+
+ QString add = ui->addEdit->text();
+
+ WalletModel::SendCoinsReturn sendStatus =model->prepareecoinaffrim(num,add,m_name);
+
+ if(sendStatus.status == WalletModel::OK)
+ {
+ Q_EMIT gotoecoinconfrimsendaffrim(num,add);
+ }
+ else
+ {
+ m_error = model->m_sendcoinerror;//20180201
+ processSendCoinsReturn(sendStatus);
+ }
+
+
+
+
+}
diff --git a/.svn/pristine/11/114676a07f49c1d5eb002660aba392147bc7a2b5.svn-base b/.svn/pristine/11/114676a07f49c1d5eb002660aba392147bc7a2b5.svn-base
new file mode 100644
index 0000000..0115dd8
--- /dev/null
+++ b/.svn/pristine/11/114676a07f49c1d5eb002660aba392147bc7a2b5.svn-base
@@ -0,0 +1,637 @@
+
+
+ eCoinSenddialog
+
+
+
+ 0
+ 0
+ 1065
+ 819
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 0
+
+
-
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 67
+
+
+
+
+ 16777215
+ 67
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 31
+ 31
+ 111
+ 16
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ name
+
+
+
+
+
+ 150
+ 30
+ 721
+ 20
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 67
+
+
+
+
+ 16777215
+ 67
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 31
+ 21
+ 111
+ 16
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ num
+
+
+
+
+
+ 150
+ 20
+ 741
+ 20
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 67
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+
+ 30
+ 30
+ 67
+ 17
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ available
+
+
+
+
+
+ 150
+ 30
+ 671
+ 17
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 67
+
+
+
+
+ 16777215
+ 67
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+
+ 30
+ 30
+ 67
+ 17
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ time
+
+
+
+
+
+ 150
+ 30
+ 541
+ 17
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 67
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+
+ 30
+ 30
+ 61
+ 16
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ accuracy
+
+
+
+
+
+ 150
+ 30
+ 67
+ 17
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 67
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+
+ 30
+ 30
+ 67
+ 17
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ hash
+
+
+
+
+
+ 150
+ 30
+ 821
+ 17
+
+
+
+ TextLabel
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 320
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 30
+ 10
+ 80
+ 20
+
+
+
+ font-size : 14px;
+color: rgb(51, 51, 51);
+
+
+ Address
+
+
+
+
+
+ 100
+ 30
+ 457
+ 291
+
+
+
+
-
+
+
+
+ 0
+ 222
+
+
+
+
+ 16777215
+ 222
+
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 110
+ 20
+
+
+
+
+ -
+
+
+
+ 200
+ 200
+
+
+
+
+ 200
+ 200
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 109
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 235
+ 50
+
+
+
+
+ 235
+ 50
+
+
+
+ background-image: url(:/res/png/buttons/235_50.png);border:none;font-size : 16px;
+color: rgb(255, 255, 255);
+
+
+ Send
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.svn/pristine/13/13690f5310717013bf741fd02b1bff842145afa1.svn-base b/.svn/pristine/13/13690f5310717013bf741fd02b1bff842145afa1.svn-base
new file mode 100644
index 0000000..2ae8a4e
--- /dev/null
+++ b/.svn/pristine/13/13690f5310717013bf741fd02b1bff842145afa1.svn-base
@@ -0,0 +1,1579 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "interpreter.h"
+
+#include "primitives/transaction.h"
+#include "crypto/ripemd160.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "pubkey.h"
+#include "script/script.h"
+#include "uint256.h"
+
+using namespace std;
+
+typedef vector valtype;
+
+namespace {
+
+inline bool set_success(ScriptError* ret)
+{
+ if (ret)
+ *ret = SCRIPT_ERR_OK;
+ return true;
+}
+
+inline bool set_error(ScriptError* ret, const ScriptError serror)
+{
+ if (ret)
+ *ret = serror;
+ return false;
+}
+
+} // anon namespace
+
+bool CastToBool(const valtype& vch)
+{
+ for (unsigned int i = 0; i < vch.size(); i++)
+ {
+ if (vch[i] != 0)
+ {
+ // Can be negative zero
+ if (i == vch.size()-1 && vch[i] == 0x80)
+ return false;
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Script is a stack machine (like Forth) that evaluates a predicate
+ * returning a bool indicating valid or not. There are no loops.
+ */
+#define stacktop(i) (stack.at(stack.size()+(i)))
+#define altstacktop(i) (altstack.at(altstack.size()+(i)))
+static inline void popstack(vector& stack)
+{
+ if (stack.empty())
+ throw runtime_error("popstack(): stack empty");
+ stack.pop_back();
+}
+
+bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
+ if (vchPubKey.size() < 33) {
+ // Non-canonical public key: too short
+ return false;
+ }
+ if (vchPubKey[0] == 0x04) {
+ if (vchPubKey.size() != 65) {
+ // Non-canonical public key: invalid length for uncompressed key
+ return false;
+ }
+ } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) {
+ if (vchPubKey.size() != 33) {
+ // Non-canonical public key: invalid length for compressed key
+ return false;
+ }
+ } else {
+ // Non-canonical public key: neither compressed nor uncompressed
+ return false;
+ }
+ return true;
+}
+
+bool static IsCompressedPubKey(const valtype &vchPubKey) {
+ if (vchPubKey.size() != 33) {
+ // Non-canonical public key: invalid length for compressed key
+ return false;
+ }
+ if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) {
+ // Non-canonical public key: invalid prefix for compressed key
+ return false;
+ }
+ return true;
+}
+
+/**
+ * A canonical signature exists of: <30> <02> <02>
+ * Where R and S are not negative (their first byte has its highest bit not set), and not
+ * excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
+ * in which case a single 0 byte is necessary and even required).
+ *
+ * See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
+ *
+ * This function is consensus-critical since BIP66.
+ */
+bool static IsValidSignatureEncoding(const std::vector &sig) {
+ // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
+ // * total-length: 1-byte length descriptor of everything that follows,
+ // excluding the sighash byte.
+ // * R-length: 1-byte length descriptor of the R value that follows.
+ // * R: arbitrary-length big-endian encoded R value. It must use the shortest
+ // possible encoding for a positive integers (which means no null bytes at
+ // the start, except a single one when the next byte has its highest bit set).
+ // * S-length: 1-byte length descriptor of the S value that follows.
+ // * S: arbitrary-length big-endian encoded S value. The same rules apply.
+ // * sighash: 1-byte value indicating what data is hashed (not part of the DER
+ // signature)
+
+ // Minimum and maximum size constraints.
+ if (sig.size() < 9) return false;
+ if (sig.size() > 73) return false;
+
+ // A signature is of type 0x30 (compound).
+ if (sig[0] != 0x30) return false;
+
+ // Make sure the length covers the entire signature.
+ if (sig[1] != sig.size() - 3) return false;
+
+ // Extract the length of the R element.
+ unsigned int lenR = sig[3];
+
+ // Make sure the length of the S element is still inside the signature.
+ if (5 + lenR >= sig.size()) return false;
+
+ // Extract the length of the S element.
+ unsigned int lenS = sig[5 + lenR];
+
+ // Verify that the length of the signature matches the sum of the length
+ // of the elements.
+ if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
+
+ // Check whether the R element is an integer.
+ if (sig[2] != 0x02) return false;
+
+ // Zero-length integers are not allowed for R.
+ if (lenR == 0) return false;
+
+ // Negative numbers are not allowed for R.
+ if (sig[4] & 0x80) return false;
+
+ // Null bytes at the start of R are not allowed, unless R would
+ // otherwise be interpreted as a negative number.
+ if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
+
+ // Check whether the S element is an integer.
+ if (sig[lenR + 4] != 0x02) return false;
+
+ // Zero-length integers are not allowed for S.
+ if (lenS == 0) return false;
+
+ // Negative numbers are not allowed for S.
+ if (sig[lenR + 6] & 0x80) return false;
+
+ // Null bytes at the start of S are not allowed, unless S would otherwise be
+ // interpreted as a negative number.
+ if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;
+
+ return true;
+}
+
+bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
+ if (!IsValidSignatureEncoding(vchSig)) {
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
+ }
+ std::vector vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1);
+ if (!CPubKey::CheckLowS(vchSigCopy)) {
+ return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
+ }
+ return true;
+}
+
+bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
+ if (vchSig.size() == 0) {
+ return false;
+ }
+ unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
+ if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
+ return false;
+
+ return true;
+}
+
+bool CheckSignatureEncoding(const vector &vchSig, unsigned int flags, ScriptError* serror) {
+ // Empty signature. Not strictly DER encoded, but allowed to provide a
+ // compact way to provide an invalid signature for use with CHECK(MULTI)SIG
+ if (vchSig.size() == 0) {
+ return true;
+ }
+ if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsValidSignatureEncoding(vchSig)) {
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
+ } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
+ // serror is set
+ return false;
+ } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
+ return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
+ }
+ return true;
+}
+
+bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) {
+ if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
+ return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
+ }
+ // Only compressed keys are accepted in segwit
+ if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PUBKEYTYPE);
+ }
+ return true;
+}
+
+bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
+ if (data.size() == 0) {
+ // Could have used OP_0.
+ return opcode == OP_0;
+ } else if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) {
+ // Could have used OP_1 .. OP_16.
+ return opcode == OP_1 + (data[0] - 1);
+ } else if (data.size() == 1 && data[0] == 0x81) {
+ // Could have used OP_1NEGATE.
+ return opcode == OP_1NEGATE;
+ } else if (data.size() <= 75) {
+ // Could have used a direct push (opcode indicating number of bytes pushed + those bytes).
+ return opcode == data.size();
+ } else if (data.size() <= 255) {
+ // Could have used OP_PUSHDATA.
+ return opcode == OP_PUSHDATA1;
+ } else if (data.size() <= 65535) {
+ // Could have used OP_PUSHDATA2.
+ return opcode == OP_PUSHDATA2;
+ }
+ return true;
+}
+
+bool EvalScript(vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
+{
+ static const CScriptNum bnZero(0);
+ static const CScriptNum bnOne(1);
+ static const CScriptNum bnFalse(0);
+ static const CScriptNum bnTrue(1);
+ static const valtype vchFalse(0);
+ static const valtype vchZero(0);
+ static const valtype vchTrue(1, 1);
+
+ CScript::const_iterator pc = script.begin();
+ CScript::const_iterator pend = script.end();
+ CScript::const_iterator pbegincodehash = script.begin();
+ opcodetype opcode;
+ valtype vchPushValue;
+ vector vfExec;
+ vector altstack;
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
+ if (script.size() > MAX_SCRIPT_SIZE)
+ return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
+ int nOpCount = 0;
+ bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;
+
+ try
+ {
+ while (pc < pend)
+ {
+ bool fExec = !count(vfExec.begin(), vfExec.end(), false);
+
+ //
+ // Read instruction
+ //
+ if (!script.GetOp(pc, opcode, vchPushValue))
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
+ if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE)
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+
+ // Note how OP_RESERVED does not count towards the opcode limit.
+ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
+
+ if (opcode == OP_CAT ||
+ opcode == OP_SUBSTR ||
+ opcode == OP_LEFT ||
+ opcode == OP_RIGHT ||
+ opcode == OP_INVERT ||
+ opcode == OP_AND ||
+ opcode == OP_OR ||
+ opcode == OP_XOR ||
+ opcode == OP_2MUL ||
+ opcode == OP_2DIV ||
+ opcode == OP_MUL ||
+ opcode == OP_DIV ||
+ opcode == OP_MOD ||
+ opcode == OP_LSHIFT ||
+ opcode == OP_RSHIFT)
+ return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
+
+ if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
+ if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {
+ return set_error(serror, SCRIPT_ERR_MINIMALDATA);
+ }
+ stack.push_back(vchPushValue);
+ } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
+ switch (opcode)
+ {
+ //
+ // Push value
+ //
+ case OP_1NEGATE:
+ case OP_1:
+ case OP_2:
+ case OP_3:
+ case OP_4:
+ case OP_5:
+ case OP_6:
+ case OP_7:
+ case OP_8:
+ case OP_9:
+ case OP_10:
+ case OP_11:
+ case OP_12:
+ case OP_13:
+ case OP_14:
+ case OP_15:
+ case OP_16:
+ {
+ // ( -- value)
+ CScriptNum bn((int)opcode - (int)(OP_1 - 1));
+ stack.push_back(bn.getvch());
+ // The result of these opcodes should always be the minimal way to push the data
+ // they push, so no need for a CheckMinimalPush here.
+ }
+ break;
+
+
+ //
+ // Control
+ //
+ case OP_NOP:
+ break;
+
+ case OP_CHECKLOCKTIMEVERIFY:
+ {
+ if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
+ // not enabled; treat as a NOP2
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
+
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // Note that elsewhere numeric opcodes are limited to
+ // operands in the range -2**31+1 to 2**31-1, however it is
+ // legal for opcodes to produce results exceeding that
+ // range. This limitation is implemented by CScriptNum's
+ // default 4-byte limit.
+ //
+ // If we kept to that limit we'd have a year 2038 problem,
+ // even though the nLockTime field in transactions
+ // themselves is uint32 which only becomes meaningless
+ // after the year 2106.
+ //
+ // Thus as a special case we tell CScriptNum to accept up
+ // to 5-byte bignums, which are good until 2**39-1, well
+ // beyond the 2**32-1 limit of the nLockTime field itself.
+ const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKLOCKTIMEVERIFY.
+ if (nLockTime < 0)
+ return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // Actually compare the specified lock time with the transaction.
+ if (!checker.CheckLockTime(nLockTime))
+ return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
+ break;
+ }
+
+ case OP_CHECKSEQUENCEVERIFY:
+ {
+ if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
+ // not enabled; treat as a NOP3
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
+
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // nSequence, like nLockTime, is a 32-bit unsigned integer
+ // field. See the comment in CHECKLOCKTIMEVERIFY regarding
+ // 5-byte numeric operands.
+ const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKSEQUENCEVERIFY.
+ if (nSequence < 0)
+ return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // To provide for future soft-fork extensibility, if the
+ // operand has the disabled lock-time flag set,
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
+ if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
+ break;
+
+ // Compare the specified sequence number with the input.
+ if (!checker.CheckSequence(nSequence))
+ return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
+ break;
+ }
+
+ case OP_NOP1: case OP_NOP4: case OP_NOP5:
+ case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
+ {
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+
+ case OP_IF:
+ case OP_NOTIF:
+ {
+ // if [statements] [else [statements]] endif
+ bool fValue = false;
+ if (fExec)
+ {
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ valtype& vch = stacktop(-1);
+ if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) {
+ if (vch.size() > 1)
+ return set_error(serror, SCRIPT_ERR_MINIMALIF);
+ if (vch.size() == 1 && vch[0] != 1)
+ return set_error(serror, SCRIPT_ERR_MINIMALIF);
+ }
+ fValue = CastToBool(vch);
+ if (opcode == OP_NOTIF)
+ fValue = !fValue;
+ popstack(stack);
+ }
+ vfExec.push_back(fValue);
+ }
+ break;
+
+ case OP_ELSE:
+ {
+ if (vfExec.empty())
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ vfExec.back() = !vfExec.back();
+ }
+ break;
+
+ case OP_ENDIF:
+ {
+ if (vfExec.empty())
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ vfExec.pop_back();
+ }
+ break;
+
+ case OP_VERIFY:
+ {
+ // (true -- ) or
+ // (false -- false) and return
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ bool fValue = CastToBool(stacktop(-1));
+ if (fValue)
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_VERIFY);
+ }
+ break;
+
+ case OP_RETURN:
+ {
+ return set_error(serror, SCRIPT_ERR_OP_RETURN);
+ }
+ break;
+
+
+ //
+ // Stack ops
+ //
+ case OP_TOALTSTACK:
+ {
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ altstack.push_back(stacktop(-1));
+ popstack(stack);
+ }
+ break;
+
+ case OP_FROMALTSTACK:
+ {
+ if (altstack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
+ stack.push_back(altstacktop(-1));
+ popstack(altstack);
+ }
+ break;
+
+ case OP_2DROP:
+ {
+ // (x1 x2 -- )
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ popstack(stack);
+ popstack(stack);
+ }
+ break;
+
+ case OP_2DUP:
+ {
+ // (x1 x2 -- x1 x2 x1 x2)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-2);
+ valtype vch2 = stacktop(-1);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ }
+ break;
+
+ case OP_3DUP:
+ {
+ // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
+ if (stack.size() < 3)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-3);
+ valtype vch2 = stacktop(-2);
+ valtype vch3 = stacktop(-1);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ stack.push_back(vch3);
+ }
+ break;
+
+ case OP_2OVER:
+ {
+ // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
+ if (stack.size() < 4)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-4);
+ valtype vch2 = stacktop(-3);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ }
+ break;
+
+ case OP_2ROT:
+ {
+ // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
+ if (stack.size() < 6)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-6);
+ valtype vch2 = stacktop(-5);
+ stack.erase(stack.end()-6, stack.end()-4);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ }
+ break;
+
+ case OP_2SWAP:
+ {
+ // (x1 x2 x3 x4 -- x3 x4 x1 x2)
+ if (stack.size() < 4)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-4), stacktop(-2));
+ swap(stacktop(-3), stacktop(-1));
+ }
+ break;
+
+ case OP_IFDUP:
+ {
+ // (x - 0 | x x)
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
+ if (CastToBool(vch))
+ stack.push_back(vch);
+ }
+ break;
+
+ case OP_DEPTH:
+ {
+ // -- stacksize
+ CScriptNum bn(stack.size());
+ stack.push_back(bn.getvch());
+ }
+ break;
+
+ case OP_DROP:
+ {
+ // (x -- )
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ popstack(stack);
+ }
+ break;
+
+ case OP_DUP:
+ {
+ // (x -- x x)
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
+ stack.push_back(vch);
+ }
+ break;
+
+ case OP_NIP:
+ {
+ // (x1 x2 -- x2)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ stack.erase(stack.end() - 2);
+ }
+ break;
+
+ case OP_OVER:
+ {
+ // (x1 x2 -- x1 x2 x1)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-2);
+ stack.push_back(vch);
+ }
+ break;
+
+ case OP_PICK:
+ case OP_ROLL:
+ {
+ // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
+ // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ int n = CScriptNum(stacktop(-1), fRequireMinimal).getint();
+ popstack(stack);
+ if (n < 0 || n >= (int)stack.size())
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-n-1);
+ if (opcode == OP_ROLL)
+ stack.erase(stack.end()-n-1);
+ stack.push_back(vch);
+ }
+ break;
+
+ case OP_ROT:
+ {
+ // (x1 x2 x3 -- x2 x3 x1)
+ // x2 x1 x3 after first swap
+ // x2 x3 x1 after second swap
+ if (stack.size() < 3)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-3), stacktop(-2));
+ swap(stacktop(-2), stacktop(-1));
+ }
+ break;
+
+ case OP_SWAP:
+ {
+ // (x1 x2 -- x2 x1)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-2), stacktop(-1));
+ }
+ break;
+
+ case OP_TUCK:
+ {
+ // (x1 x2 -- x2 x1 x2)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
+ stack.insert(stack.end()-2, vch);
+ }
+ break;
+
+
+ case OP_SIZE:
+ {
+ // (in -- in size)
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn(stacktop(-1).size());
+ stack.push_back(bn.getvch());
+ }
+ break;
+
+
+ //
+ // Bitwise logic
+ //
+ case OP_EQUAL:
+ case OP_EQUALVERIFY:
+ //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
+ {
+ // (x1 x2 - bool)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype& vch1 = stacktop(-2);
+ valtype& vch2 = stacktop(-1);
+ bool fEqual = (vch1 == vch2);
+ // OP_NOTEQUAL is disabled because it would be too easy to say
+ // something like n != 1 and have some wiseguy pass in 1 with extra
+ // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
+ //if (opcode == OP_NOTEQUAL)
+ // fEqual = !fEqual;
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(fEqual ? vchTrue : vchFalse);
+ if (opcode == OP_EQUALVERIFY)
+ {
+ if (fEqual)
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_EQUALVERIFY);
+ }
+ }
+ break;
+
+
+ //
+ // Numeric
+ //
+ case OP_1ADD:
+ case OP_1SUB:
+ case OP_NEGATE:
+ case OP_ABS:
+ case OP_NOT:
+ case OP_0NOTEQUAL:
+ {
+ // (in -- out)
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn(stacktop(-1), fRequireMinimal);
+ switch (opcode)
+ {
+ case OP_1ADD: bn += bnOne; break;
+ case OP_1SUB: bn -= bnOne; break;
+ case OP_NEGATE: bn = -bn; break;
+ case OP_ABS: if (bn < bnZero) bn = -bn; break;
+ case OP_NOT: bn = (bn == bnZero); break;
+ case OP_0NOTEQUAL: bn = (bn != bnZero); break;
+ default: assert(!"invalid opcode"); break;
+ }
+ popstack(stack);
+ stack.push_back(bn.getvch());
+ }
+ break;
+
+ case OP_ADD:
+ case OP_SUB:
+ case OP_BOOLAND:
+ case OP_BOOLOR:
+ case OP_NUMEQUAL:
+ case OP_NUMEQUALVERIFY:
+ case OP_NUMNOTEQUAL:
+ case OP_LESSTHAN:
+ case OP_GREATERTHAN:
+ case OP_LESSTHANOREQUAL:
+ case OP_GREATERTHANOREQUAL:
+ case OP_MIN:
+ case OP_MAX:
+ {
+ // (x1 x2 -- out)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn1(stacktop(-2), fRequireMinimal);
+ CScriptNum bn2(stacktop(-1), fRequireMinimal);
+ CScriptNum bn(0);
+ switch (opcode)
+ {
+ case OP_ADD:
+ bn = bn1 + bn2;
+ break;
+
+ case OP_SUB:
+ bn = bn1 - bn2;
+ break;
+
+ case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break;
+ case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break;
+ case OP_NUMEQUAL: bn = (bn1 == bn2); break;
+ case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break;
+ case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break;
+ case OP_LESSTHAN: bn = (bn1 < bn2); break;
+ case OP_GREATERTHAN: bn = (bn1 > bn2); break;
+ case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
+ case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
+ case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
+ case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
+ default: assert(!"invalid opcode"); break;
+ }
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(bn.getvch());
+
+ if (opcode == OP_NUMEQUALVERIFY)
+ {
+ if (CastToBool(stacktop(-1)))
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY);
+ }
+ }
+ break;
+
+ case OP_WITHIN:
+ {
+ // (x min max -- out)
+ if (stack.size() < 3)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn1(stacktop(-3), fRequireMinimal);
+ CScriptNum bn2(stacktop(-2), fRequireMinimal);
+ CScriptNum bn3(stacktop(-1), fRequireMinimal);
+ bool fValue = (bn2 <= bn1 && bn1 < bn3);
+ popstack(stack);
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(fValue ? vchTrue : vchFalse);
+ }
+ break;
+
+
+ //
+ // Crypto
+ //
+ case OP_RIPEMD160:
+ case OP_SHA1:
+ case OP_SHA256:
+ case OP_HASH160:
+ case OP_HASH256:
+ {
+ // (in -- hash)
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype& vch = stacktop(-1);
+ valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
+ if (opcode == OP_RIPEMD160)
+ CRIPEMD160().Write(vch.data(), vch.size()).Finalize(vchHash.data());
+ else if (opcode == OP_SHA1)
+ CSHA1().Write(vch.data(), vch.size()).Finalize(vchHash.data());
+ else if (opcode == OP_SHA256)
+ CSHA256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
+ else if (opcode == OP_HASH160)
+ CHash160().Write(vch.data(), vch.size()).Finalize(vchHash.data());
+ else if (opcode == OP_HASH256)
+ CHash256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
+ popstack(stack);
+ stack.push_back(vchHash);
+ }
+ break;
+
+ case OP_CODESEPARATOR:
+ {
+ // Hash starts after the code separator
+ pbegincodehash = pc;
+ }
+ break;
+
+ case OP_CHECKSIG:
+ case OP_CHECKSIGVERIFY:
+ {
+ // (sig pubkey -- bool)
+ if (stack.size() < 2)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ valtype& vchSig = stacktop(-2);
+ valtype& vchPubKey = stacktop(-1);
+
+ // Subset of script starting at the most recent codeseparator
+ CScript scriptCode(pbegincodehash, pend);
+
+ // Drop the signature in pre-segwit scripts but not segwit scripts
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
+
+ if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
+ //serror is set
+ return false;
+ }
+ bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
+
+ if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
+
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(fSuccess ? vchTrue : vchFalse);
+ if (opcode == OP_CHECKSIGVERIFY)
+ {
+ if (fSuccess)
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
+ }
+ }
+ break;
+
+ case OP_CHECKMULTISIG:
+ case OP_CHECKMULTISIGVERIFY:
+ {
+ // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
+
+ int i = 1;
+ if ((int)stack.size() < i)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
+ if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
+ return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
+ nOpCount += nKeysCount;
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
+ int ikey = ++i;
+ // ikey2 is the position of last non-signature item in the stack. Top stack item = 1.
+ // With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails.
+ int ikey2 = nKeysCount + 2;
+ i += nKeysCount;
+ if ((int)stack.size() < i)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
+ if (nSigsCount < 0 || nSigsCount > nKeysCount)
+ return set_error(serror, SCRIPT_ERR_SIG_COUNT);
+ int isig = ++i;
+ i += nSigsCount;
+ if ((int)stack.size() < i)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // Subset of script starting at the most recent codeseparator
+ CScript scriptCode(pbegincodehash, pend);
+
+ // Drop the signature in pre-segwit scripts but not segwit scripts
+ for (int k = 0; k < nSigsCount; k++)
+ {
+ valtype& vchSig = stacktop(-isig-k);
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
+ }
+
+ bool fSuccess = true;
+ while (fSuccess && nSigsCount > 0)
+ {
+ valtype& vchSig = stacktop(-isig);
+ valtype& vchPubKey = stacktop(-ikey);
+
+ // Note how this makes the exact order of pubkey/signature evaluation
+ // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set.
+ // See the script_(in)valid tests for details.
+ if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
+ // serror is set
+ return false;
+ }
+
+ // Check signature
+ bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
+
+ if (fOk) {
+ isig++;
+ nSigsCount--;
+ }
+ ikey++;
+ nKeysCount--;
+
+ // If there are more signatures left than keys left,
+ // then too many signatures have failed. Exit early,
+ // without checking any further signatures.
+ if (nSigsCount > nKeysCount)
+ fSuccess = false;
+ }
+
+ // Clean up stack of actual arguments
+ while (i-- > 1) {
+ // If the operation failed, we require that all signatures must be empty vector
+ if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
+ if (ikey2 > 0)
+ ikey2--;
+ popstack(stack);
+ }
+
+ // A bug causes CHECKMULTISIG to consume one extra argument
+ // whose contents were not checked in any way.
+ //
+ // Unfortunately this is a potential source of mutability,
+ // so optionally verify it is exactly equal to zero prior
+ // to removing it from the stack.
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY);
+ popstack(stack);
+
+ stack.push_back(fSuccess ? vchTrue : vchFalse);
+
+ if (opcode == OP_CHECKMULTISIGVERIFY)
+ {
+ if (fSuccess)
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+ }
+ break;
+
+ default:
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
+ }
+
+ // Size limits
+ if (stack.size() + altstack.size() > 1000)
+ return set_error(serror, SCRIPT_ERR_STACK_SIZE);
+ }
+ }
+ catch (...)
+ {
+ return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
+ }
+
+ if (!vfExec.empty())
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+
+ return set_success(serror);
+}
+
+namespace {
+
+/**
+ * Wrapper that serializes like CTransaction, but with the modifications
+ * required for the signature hash done in-place
+ */
+class CTransactionSignatureSerializer {
+private:
+ const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const CScript& scriptCode; //!< output script being consumed
+ const unsigned int nIn; //!< input index of txTo being signed
+ const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
+
+public:
+ CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
+ txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
+ fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
+ fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
+ fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}
+
+ /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
+ template
+ void SerializeScriptCode(S &s) const {
+ CScript::const_iterator it = scriptCode.begin();
+ CScript::const_iterator itBegin = it;
+ opcodetype opcode;
+ unsigned int nCodeSeparators = 0;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR)
+ nCodeSeparators++;
+ }
+ ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
+ it = itBegin;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR) {
+ s.write((char*)&itBegin[0], it-itBegin-1);
+ itBegin = it;
+ }
+ }
+ if (itBegin != scriptCode.end())
+ s.write((char*)&itBegin[0], it-itBegin);
+ }
+
+ /** Serialize an input of txTo */
+ template
+ void SerializeInput(S &s, unsigned int nInput) const {
+ // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
+ if (fAnyoneCanPay)
+ nInput = nIn;
+ // Serialize the prevout
+ ::Serialize(s, txTo.vin[nInput].prevout);
+ // Serialize the script
+ if (nInput != nIn)
+ // Blank out other inputs' signatures
+ ::Serialize(s, CScriptBase());
+ else
+ SerializeScriptCode(s);
+ // Serialize the nSequence
+ if (nInput != nIn && (fHashSingle || fHashNone))
+ // let the others update at will
+ ::Serialize(s, (int)0);
+ else
+ ::Serialize(s, txTo.vin[nInput].nSequence);
+ }
+
+ /** Serialize an output of txTo */
+ template
+ void SerializeOutput(S &s, unsigned int nOutput) const {
+ if (fHashSingle && nOutput != nIn)
+ // Do not lock-in the txout payee at other indices as txin
+ ::Serialize(s, CTxOut());
+ else
+ ::Serialize(s, txTo.vout[nOutput]);
+ }
+
+ /** Serialize txTo */
+ template
+ void Serialize(S &s) const {
+ // Serialize nVersion
+ ::Serialize(s, txTo.nVersion);
+ // Serialize vin
+ unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
+ ::WriteCompactSize(s, nInputs);
+ for (unsigned int nInput = 0; nInput < nInputs; nInput++)
+ SerializeInput(s, nInput);
+ // Serialize vout
+ unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
+ ::WriteCompactSize(s, nOutputs);
+ for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
+ SerializeOutput(s, nOutput);
+ // Serialize nLockTime
+ ::Serialize(s, txTo.nLockTime);
+ }
+};
+
+uint256 GetPrevoutHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].prevout;
+ }
+ return ss.GetHash();
+}
+
+uint256 GetSequenceHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].nSequence;
+ }
+ return ss.GetHash();
+}
+
+uint256 GetOutputsHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vout.size(); n++) {
+ ss << txTo.vout[n];
+ }
+ return ss.GetHash();
+}
+
+} // anon namespace
+
+PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
+{
+ hashPrevouts = GetPrevoutHash(txTo);
+ hashSequence = GetSequenceHash(txTo);
+ hashOutputs = GetOutputsHash(txTo);
+}
+
+uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
+{
+ if (sigversion == SIGVERSION_WITNESS_V0) {
+ uint256 hashPrevouts;
+ uint256 hashSequence;
+ uint256 hashOutputs;
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY)) {
+ hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
+ }
+
+ if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
+ }
+
+
+ if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo);
+ } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTo.vout[nIn];
+ hashOutputs = ss.GetHash();
+ }
+
+ CHashWriter ss(SER_GETHASH, 0);
+ // Version
+ ss << txTo.nVersion;
+ // Input prevouts/nSequence (none/all, depending on flags)
+ ss << hashPrevouts;
+ ss << hashSequence;
+ // The input being signed (replacing the scriptSig with scriptCode + amount)
+ // The prevout may already be contained in hashPrevout, and the nSequence
+ // may already be contain in hashSequence.
+ ss << txTo.vin[nIn].prevout;
+ ss << static_cast(scriptCode);
+ ss << amount;
+ ss << txTo.vin[nIn].nSequence;
+ // Outputs (none/one/all, depending on flags)
+ ss << hashOutputs;
+ // Locktime
+ ss << txTo.nLockTime;
+ // Sighash type
+ ss << nHashType;
+
+ return ss.GetHash();
+ }
+
+ static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
+ if (nIn >= txTo.vin.size()) {
+ // nIn out of range
+ return one;
+ }
+
+ // Check for invalid use of SIGHASH_SINGLE
+ if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
+ if (nIn >= txTo.vout.size()) {
+ // nOut out of range
+ return one;
+ }
+ }
+
+ // Wrapper to serialize only the necessary parts of the transaction being signed
+ CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
+
+ // Serialize and hash
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTmp << nHashType;
+ return ss.GetHash();
+}
+
+bool TransactionSignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+{
+ return pubkey.Verify(sighash, vchSig);
+}
+
+bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn, const vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
+{
+ CPubKey pubkey(vchPubKey);
+ if (!pubkey.IsValid())
+ return false;
+
+ // Hash type is one byte tacked on to the end of the signature
+ vector vchSig(vchSigIn);
+ if (vchSig.empty())
+ return false;
+ int nHashType = vchSig.back();
+ vchSig.pop_back();
+
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata);
+
+ if (!VerifySignature(vchSig, pubkey, sighash))
+ return false;
+
+ return true;
+}
+
+bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
+{
+ // There are two kinds of nLockTime: lock-by-blockheight
+ // and lock-by-blocktime, distinguished by whether
+ // nLockTime < LOCKTIME_THRESHOLD.
+ //
+ // We want to compare apples to apples, so fail the script
+ // unless the type of nLockTime being tested is the same as
+ // the nLockTime in the transaction.
+ if (!(
+ (txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
+ (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
+ ))
+ return false;
+
+ // Now that we know we're comparing apples-to-apples, the
+ // comparison is a simple numeric one.
+ if (nLockTime > (int64_t)txTo->nLockTime)
+ return false;
+
+ // Finally the nLockTime feature can be disabled and thus
+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been
+ // finalized by setting nSequence to maxint. The
+ // transaction would be allowed into the blockchain, making
+ // the opcode ineffective.
+ //
+ // Testing if this vin is not final is sufficient to
+ // prevent this condition. Alternatively we could test all
+ // inputs, but testing just this input minimizes the data
+ // required to prove correct CHECKLOCKTIMEVERIFY execution.
+ if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence)
+ return false;
+
+ return true;
+}
+
+bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
+{
+ // Relative lock times are supported by comparing the passed
+ // in operand to the sequence number of the input.
+ const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
+
+ // Fail if the transaction's version number is not set high
+ // enough to trigger BIP 68 rules.
+ if (static_cast(txTo->nVersion) < 2)
+ return false;
+
+ // Sequence numbers with their most significant bit set are not
+ // consensus constrained. Testing that the transaction's sequence
+ // number do not have this bit set prevents using this property
+ // to get around a CHECKSEQUENCEVERIFY check.
+ if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
+ return false;
+
+ // Mask off any bits that do not have consensus-enforced meaning
+ // before doing the integer comparisons
+ const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
+ const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
+ const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
+
+ // There are two kinds of nSequence: lock-by-blockheight
+ // and lock-by-blocktime, distinguished by whether
+ // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
+ //
+ // We want to compare apples to apples, so fail the script
+ // unless the type of nSequenceMasked being tested is the same as
+ // the nSequenceMasked in the transaction.
+ if (!(
+ (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
+ (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
+ )) {
+ return false;
+ }
+
+ // Now that we know we're comparing apples-to-apples, the
+ // comparison is a simple numeric one.
+ if (nSequenceMasked > txToSequenceMasked)
+ return false;
+
+ return true;
+}
+
+static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+{
+ vector > stack;
+ CScript scriptPubKey;
+
+ if (witversion == 0) {
+ if (program.size() == 32) {
+ // Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness
+ if (witness.stack.size() == 0) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
+ }
+ scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
+ stack = std::vector >(witness.stack.begin(), witness.stack.end() - 1);
+ uint256 hashScriptPubKey;
+ CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
+ if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+ }
+ } else if (program.size() == 20) {
+ // Special case for pay-to-pubkeyhash; signature + pubkey in witness
+ if (witness.stack.size() != 2) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
+ }
+ scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
+ stack = witness.stack;
+ } else {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
+ }
+ } else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ } else {
+ // Higher version witness scripts return true for future softfork compatibility
+ return set_success(serror);
+ }
+
+ // Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
+ for (unsigned int i = 0; i < stack.size(); i++) {
+ if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE)
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
+ }
+
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) {
+ return false;
+ }
+
+ // Scripts inside witness implicitly require cleanstack behaviour
+ if (stack.size() != 1)
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stack.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ return true;
+}
+
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
+{
+ static const CScriptWitness emptyWitness;
+ if (witness == NULL) {
+ witness = &emptyWitness;
+ }
+ bool hadWitness = false;
+
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
+
+ if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
+ }
+
+ vector > stack, stackCopy;
+ if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
+ {
+ // serror is set
+ return false;
+ }
+
+ if (flags & SCRIPT_VERIFY_P2SH)
+ stackCopy = stack;
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
+ {
+ // serror is set
+ return false;
+ }
+
+ if (stack.empty())
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (CastToBool(stack.back()) == false)
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+
+ // Bare witness programs
+ int witnessversion;
+ std::vector witnessprogram;
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig.size() != 0) {
+ // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
+
+ // Additional validation for spend-to-script-hash transactions:
+ if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
+ {
+ // scriptSig must be literals-only or validation fails
+ if (!scriptSig.IsPushOnly())
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
+
+ // Restore stack.
+ swap(stack, stackCopy);
+
+ // stack cannot be empty here, because if it was the
+ // P2SH HASH <> EQUAL scriptPubKey would be evaluated with
+ // an empty stack and the EvalScript above would return false.
+ assert(!stack.empty());
+
+ const valtype& pubKeySerialized = stack.back();
+ CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
+ popstack(stack);
+
+ if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
+ // serror is set
+ return false;
+ if (stack.empty())
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stack.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+
+ // P2SH witness program
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) {
+ hadWitness = true;
+ if (scriptSig != CScript() << std::vector(pubKey2.begin(), pubKey2.end())) {
+ // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we
+ // reintroduce malleability.
+ return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH);
+ }
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ return false;
+ }
+ // Bypass the cleanstack check at the end. The actual stack is obviously not clean
+ // for witness programs.
+ stack.resize(1);
+ }
+ }
+ }
+
+ // The CLEANSTACK check is only performed after potential P2SH evaluation,
+ // as the non-P2SH evaluation of a P2SH script will obviously not result in
+ // a clean stack (the P2SH inputs remain). The same holds for witness evaluation.
+ if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
+ // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
+ // would be possible, which is not a softfork (and P2SH should be one).
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ assert((flags & SCRIPT_VERIFY_WITNESS) != 0);
+ if (stack.size() != 1) {
+ return set_error(serror, SCRIPT_ERR_CLEANSTACK);
+ }
+ }
+
+ if (flags & SCRIPT_VERIFY_WITNESS) {
+ // We can't check for correct unexpected witness data if P2SH was off, so require
+ // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be
+ // possible, which is not a softfork.
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+ if (!hadWitness && !witness->IsNull()) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED);
+ }
+ }
+
+ return set_success(serror);
+}
+
+size_t static WitnessSigOps(int witversion, const std::vector& witprogram, const CScriptWitness& witness, int flags)
+{
+ if (witversion == 0) {
+ if (witprogram.size() == 20)
+ return 1;
+
+ if (witprogram.size() == 32 && witness.stack.size() > 0) {
+ CScript subscript(witness.stack.back().begin(), witness.stack.back().end());
+ return subscript.GetSigOpCount(true);
+ }
+ }
+
+ // Future flags may be implemented here.
+ return 0;
+}
+
+size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags)
+{
+ static const CScriptWitness witnessEmpty;
+
+ if ((flags & SCRIPT_VERIFY_WITNESS) == 0) {
+ return 0;
+ }
+ assert((flags & SCRIPT_VERIFY_P2SH) != 0);
+
+ int witnessversion;
+ std::vector witnessprogram;
+ if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+
+ if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) {
+ CScript::const_iterator pc = scriptSig.begin();
+ vector data;
+ while (pc < scriptSig.end()) {
+ opcodetype opcode;
+ scriptSig.GetOp(pc, opcode, data);
+ }
+ CScript subscript(data.begin(), data.end());
+ if (subscript.IsWitnessProgram(witnessversion, witnessprogram)) {
+ return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
+ }
+ }
+
+ return 0;
+}
diff --git a/.svn/pristine/16/161e4584aed75b864808fd4409ddf75fa8ea329e.svn-base b/.svn/pristine/16/161e4584aed75b864808fd4409ddf75fa8ea329e.svn-base
new file mode 100644
index 0000000..d998ba8
--- /dev/null
+++ b/.svn/pristine/16/161e4584aed75b864808fd4409ddf75fa8ea329e.svn-base
@@ -0,0 +1,746 @@
+
+
+ recvipchistory
+
+
+
+ 0
+ 0
+ 953
+ 675
+
+
+
+ Form
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 951
+ 708
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 191
+
+
+
+
+ 16777215
+ 191
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
+ 0
+
+
-
+
+
+ 7
+
+
-
+
+
+
+ 41
+ 41
+
+
+
+
+ 41
+ 41
+
+
+
+ background-image: url(:/res/png/recvicon.png);border:none
+
+
+
+
+
+
+
+ -
+
+
+ IsRecv
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 82
+
+
+
+
+ 16777215
+ 82
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 13
+
+
+
+ background-color: rgb(242, 241, 240);
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
+ 0
+
+
+ 7
+
+
-
+
+
+ ipctype
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ TextLabel
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
+ 15
+
+
-
+
+
+ authtype
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 566
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
+ 15
+
+
-
+
+
+ authlimit
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 566
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
+ 15
+
+
-
+
+
+ authdate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 566
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
+ 15
+
+
-
+
+
+ fee
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 779
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+
+ 30
+
+
+ 15
+
+
-
+
+
+ add
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 807
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+ Qt::TextSelectableByMouse
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
-
+
+
+ ipcdate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ TextLabel
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 61
+
+
+
+
+ 16777215
+ 61
+
+
+
+ border:none
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 30
+
+
-
+
+
-
+
+
+ ipcinfo
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.svn/pristine/1a/1a2a9df568d7ffbe07e6de2e2972fd27fa8803d1.svn-base b/.svn/pristine/1a/1a2a9df568d7ffbe07e6de2e2972fd27fa8803d1.svn-base
new file mode 100644
index 0000000..39c9476
Binary files /dev/null and b/.svn/pristine/1a/1a2a9df568d7ffbe07e6de2e2972fd27fa8803d1.svn-base differ
diff --git a/.svn/pristine/1a/1a34e14505778529c52448ea3757f7afb60aa901.svn-base b/.svn/pristine/1a/1a34e14505778529c52448ea3757f7afb60aa901.svn-base
new file mode 100644
index 0000000..b8ea08d
--- /dev/null
+++ b/.svn/pristine/1a/1a34e14505778529c52448ea3757f7afb60aa901.svn-base
@@ -0,0 +1,84 @@
+#ifndef ADDBOOKWIDGET_H
+#define ADDBOOKWIDGET_H
+
+class AddressTableModel;
+class AddModel;
+#include
+#include
+#include
+#include "guiutil.h"
+#include
+#include
+#include
+#include "MyLabel.h"
+using namespace std;
+
+QT_BEGIN_NAMESPACE
+class QItemSelection;
+class QMenu;
+class QModelIndex;
+class QSortFilterProxyModel;
+class QTableView;
+class MyItemDelegate;
+class MyStandardItemModel;
+
+QT_END_NAMESPACE
+namespace Ui {
+class AddBookWidget;
+}
+;
+
+struct txchangmap{
+ QString txadd;
+ QString txlabel;
+};
+class AddBookWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit AddBookWidget(QWidget *parent = 0);
+ ~AddBookWidget();
+ enum TabTypes {
+ TAB_send = 2,
+ TAB_set = 5,
+ TAB_other = 3
+ };
+ QString returnaddress;
+ int addnewoneipcmessage(int pictype,QString name,QString add,int picprogess);
+ bool AddEditedRow(QString key,QString value);
+ void setModel(AddressTableModel *_model);
+ void selectNewAddress(const QModelIndex &parent, int begin, int /*end*/);
+ //void setModel(WalletModel *model);
+ QStandardItemModel *student_model;
+
+ bool eventFilter(QObject *obj, QEvent *event);
+ void settag(int tag);
+
+ int gettag();
+
+Q_SIGNALS:
+ void backSend();
+ void selectaddressyes(QString a,QString b);
+ void textChanged(QString text);
+public Q_SLOTS:
+ void on_backButton_pressed();
+ void txChanged(QString t,QString add);
+ void presswSlot(QString t,QString add);
+private:
+ QLineEdit* namelabel ;
+ QLabel* namelabel0 ;
+ QLabel* timelabel ;
+ QLineEdit* timelabel0;
+ int etag ;
+ Ui::AddBookWidget *ui;
+ AddressTableModel *model;
+ AddModel *modelmodel;
+ QSortFilterProxyModel *proxyModel;
+ QSortFilterProxyModel *proxyModelnew;
+ QVBoxLayout * pvboxlayoutall;
+ std::unique_ptr filter;
+ map my_Map;
+};
+
+#endif // ADDBOOKWIDGET_H
diff --git a/.svn/pristine/1b/1b2a5e3608e4039e663b87ba87af5bcd0b791892.svn-base b/.svn/pristine/1b/1b2a5e3608e4039e663b87ba87af5bcd0b791892.svn-base
new file mode 100644
index 0000000..f2f0be3
--- /dev/null
+++ b/.svn/pristine/1b/1b2a5e3608e4039e663b87ba87af5bcd0b791892.svn-base
@@ -0,0 +1,411 @@
+// Copyright (c) 2011-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QT_WALLETMODEL_H
+#define BITCOIN_QT_WALLETMODEL_H
+
+#include "paymentrequestplus.h"
+#include "walletmodeltransaction.h"
+
+#include "support/allocators/secure.h"
+
+#include