-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathcfdcore_elements_script.cpp
157 lines (137 loc) · 4.63 KB
/
cfdcore_elements_script.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright 2019 CryptoGarage
/**
* @file cfdcore_elements_script.cpp
*
* @brief definition of script class that supports Elements
*/
#ifndef CFD_DISABLE_ELEMENTS
#include "cfdcore/cfdcore_elements_script.h"
#include <algorithm>
#include <string>
#include <vector>
#include "cfdcore/cfdcore_bytedata.h"
#include "cfdcore/cfdcore_iterator.h"
#include "cfdcore/cfdcore_logger.h"
#include "cfdcore/cfdcore_script.h"
#include "cfdcore/cfdcore_util.h"
#include "cfdcore_wally_util.h" // NOLINT
namespace cfd {
namespace core {
using logger::info;
using logger::warn;
// -----------------------------------------------------------------------------
// ContractHashUtil
// -----------------------------------------------------------------------------
Script ContractHashUtil::GetContractScript(
const Script& claim_script, const Script& fedpeg_script) {
bool is_liquidv1_watchman = CheckLiquidV1Watchman(fedpeg_script);
ScriptBuilder builder;
ByteData claim_script_data = claim_script.GetData();
bool liquidv1_op_else = false;
ByteData pubkey_data;
ByteData256 tweak;
for (const ScriptElement& element : fedpeg_script.GetElementList()) {
if (is_liquidv1_watchman &&
(element.GetOpCode() == ScriptOperator::OP_ELSE)) {
liquidv1_op_else = true;
}
ByteData data = element.GetBinaryData();
if ((!liquidv1_op_else) && element.IsBinary() &&
(data.GetDataSize() == Pubkey::kCompressedPubkeySize)) {
tweak = CryptoUtil::HmacSha256(data.GetBytes(), claim_script_data);
pubkey_data = WallyUtil::AddTweakPubkey(data, tweak, true);
builder.AppendData(pubkey_data);
} else {
builder.AppendElement(element);
}
}
return builder.Build();
}
bool ContractHashUtil::CheckLiquidV1Watchman(const Script& script) {
try {
std::vector<ScriptElement> list = script.GetElementList();
if (list.empty()) {
warn(CFD_LOG_SOURCE, "script empty.");
return false;
}
IteratorWrapper<ScriptElement> ite(list, "Check LiquidV1 Watchman NG");
if (ite.next().GetOpCode() != ScriptOperator::OP_DEPTH) {
// warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
// Does not log if it is different from the beginning of the script
return false;
}
ScriptElement element(0);
if (!ite.next().IsNumber()) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
if (ite.next().GetOpCode() != ScriptOperator::OP_EQUAL) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
if (ite.next().GetOpCode() != ScriptOperator::OP_IF) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
element = ite.next();
if (!(element.IsOpCode() && element.IsNumber())) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
int64_t req_num = element.GetNumber();
// check pubkey
element = ite.next();
while (element.GetOpCode() != ScriptOperator::OP_ELSE) {
if ((!element.IsOpCode()) && (!element.IsBinary())) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
element = ite.next();
}
if (!ite.next().IsNumber()) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
if (ite.next().GetOpCode() != ScriptOperator::OP_CHECKSEQUENCEVERIFY) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
if (ite.next().GetOpCode() != ScriptOperator::OP_DROP) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
element = ite.next();
if (!(element.IsOpCode() && element.IsNumber())) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
int64_t req_num2 = element.GetNumber();
if (req_num == req_num2) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
element = ite.next();
while (element.GetOpCode() != ScriptOperator::OP_ENDIF) {
if ((!element.IsOpCode()) && (!element.IsBinary())) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
element = ite.next();
}
if (ite.next().GetOpCode() != ScriptOperator::OP_CHECKMULTISIG) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
if (ite.hasNext()) {
warn(CFD_LOG_SOURCE, "LiquidV1 watchman script fail.");
return false;
}
return true;
} catch (...) {
warn(CFD_LOG_SOURCE, "Check LiquidV1 Watchman exception.");
return false;
}
}
} // namespace core
} // namespace cfd
#endif // CFD_DISABLE_ELEMENTS