Skip to content

Commit 955d365

Browse files
committed
binana.py: Soft fork definition via json file
1 parent f2300b4 commit 955d365

File tree

18 files changed

+280
-12
lines changed

18 files changed

+280
-12
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
*.pyc
77

8+
src/binana.h
9+
810
# Only ignore unexpected patches
911
*.patch
1012
!contrib/guix/patches/*.patch

src/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ add_custom_target(generate_build_info
8585
COMMENT "Generating bitcoin-build-info.h"
8686
VERBATIM
8787
)
88+
add_custom_target(generate_binana_info
89+
BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/binana.h ${CMAKE_SOURCE_DIR}/test/functional/data/binana.json
90+
COMMAND ${PYTHON_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/binana.py ${CMAKE_CURRENT_SOURCE_DIR}/binana/ ${CMAKE_CURRENT_SOURCE_DIR}/binana.h ${CMAKE_SOURCE_DIR}/test/functional/data/binana.json
91+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
92+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binana.py
93+
COMMENT "Generating src/binana.h and test/functional/data/binana.json"
94+
VERBATIM
95+
)
8896
add_library(bitcoin_clientversion STATIC EXCLUDE_FROM_ALL
8997
clientversion.cpp
9098
)
@@ -93,6 +101,7 @@ target_link_libraries(bitcoin_clientversion
93101
core_interface
94102
)
95103
add_dependencies(bitcoin_clientversion generate_build_info)
104+
add_dependencies(bitcoin_clientversion generate_binana_info)
96105

97106
add_subdirectory(crypto)
98107
add_subdirectory(util)
@@ -119,6 +128,7 @@ target_link_libraries(bitcoin_consensus
119128
bitcoin_crypto
120129
secp256k1
121130
)
131+
add_dependencies(bitcoin_consensus generate_binana_info)
122132

123133
if(WITH_ZMQ)
124134
add_subdirectory(zmq)
@@ -189,6 +199,7 @@ target_link_libraries(bitcoin_common
189199
$<TARGET_NAME_IF_EXISTS:USDT::headers>
190200
$<$<PLATFORM_ID:Windows>:ws2_32>
191201
)
202+
add_dependencies(bitcoin_common generate_binana_info)
192203

193204
include(InstallBinaryComponent)
194205

@@ -325,6 +336,7 @@ target_link_libraries(bitcoin_node
325336
$<TARGET_NAME_IF_EXISTS:libevent::pthreads>
326337
$<TARGET_NAME_IF_EXISTS:USDT::headers>
327338
)
339+
add_dependencies(bitcoin_node generate_binana_info)
328340

329341

330342
# Bitcoin Core bitcoind.

src/binana.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import contextlib
5+
import datetime
6+
import io
7+
import json
8+
import os
9+
import sys
10+
11+
DISABLED_OPCODES = "CAT SUBSTR LEFT RIGHT INVERT AND OR XOR 2MUL 2DIV MUL DIV MOD LSHIFT RSHIFT".split()
12+
13+
def all_ints(*v):
14+
return all(isinstance(i, int) for i in v)
15+
16+
@contextlib.contextmanager
17+
def ConditionalWriter(filename):
18+
f = io.StringIO()
19+
yield f
20+
data = f.getvalue()
21+
22+
if os.path.exists(filename):
23+
old_data = open(filename, "r", encoding="utf8").read()
24+
if data == old_data:
25+
return
26+
27+
out = open(filename, "w", encoding="utf8")
28+
out.write(data)
29+
out.close()
30+
31+
def get_binana_info(path):
32+
data = {}
33+
if not os.path.exists(path):
34+
return data
35+
36+
for f in os.scandir(path):
37+
if not f.is_file():
38+
continue
39+
d = json.load(open(f, "rb"))
40+
if isinstance(d, dict) and "binana" in d:
41+
y,n,r = d["binana"]
42+
d["filename"] = f.path
43+
if all_ints(y, n, r):
44+
data[y,n,r] = d
45+
return data
46+
47+
def gen_binana_h(data, header, depjson):
48+
script_verify_bit = 30 # count backwards; 31 is assumed unused in unit tests
49+
50+
defines = {a: [] for a in "DEPLOYMENTS DEPLOYMENTS_SIGNET DEPLOYMENTS_REGTEST DEPLOYMENTS_GBT VERIFY_FLAGS VERIFY_FLAGS_NAMES STANDARD_VERIFY_FLAGS OPCODES OPCODE_NAMES SUCCESS_OPCODES SCRIPTERR SCRIPTERR_STRING SCRIPTERR_TEST_NAMES CONSENSUS_CHECKS POLICY_CHECKS".split()}
51+
52+
jsoninfo = {"script_flags": [], "deployments": {}}
53+
54+
for y,n,r in sorted(data.keys()):
55+
b = data[y,n,r]
56+
if "deployment" not in b:
57+
continue
58+
59+
dep = b["deployment"]
60+
61+
start = int(datetime.datetime(y,1,1,tzinfo=datetime.timezone.utc).timestamp())
62+
timeout = int(datetime.datetime(y+10,1,1,tzinfo=datetime.timezone.utc).timestamp())
63+
if "start" in b:
64+
start = b["start"]
65+
if "timeout" in b:
66+
timeout = b["timeout"]
67+
68+
defines["DEPLOYMENTS"].append(f'DEPLOYMENT_{dep},')
69+
70+
defines["DEPLOYMENTS_SIGNET"].append("consensus.vDeployments[Consensus::DEPLOYMENT_%s] = SetupDeployment{.year = %d, .number = %d, .revision = %d, .start = %d, .timeout = %d, .period=432};" % (dep, y, n, r, start, timeout))
71+
defines["DEPLOYMENTS_REGTEST"].append("consensus.vDeployments[Consensus::DEPLOYMENT_%s] = SetupDeployment{.year = %d, .number = %d, .revision = %d, .always = true, .period=144};" % (dep, y, n, r))
72+
73+
jsoninfo["deployments"][dep.lower()] = {
74+
"type": "heretical",
75+
"active": True,
76+
"height": 0,
77+
"heretical": {
78+
"binana-id": "BIN-%4d-%04d-%03d" % (y,n,r),
79+
"start_time": -1,
80+
"timeout": 0x7fffffffffffffff,
81+
"period": 144,
82+
"status": "active",
83+
"status_next": "active",
84+
"since": 0
85+
}
86+
}
87+
88+
defines["DEPLOYMENTS_GBT"].append('{.name="%s", .gbt_force=true},' % (dep.lower()))
89+
90+
if b.get("scriptverify", False):
91+
jsoninfo["script_flags"].append(dep)
92+
93+
defines["VERIFY_FLAGS"].append(f'SCRIPT_VERIFY_{dep} = (1U << {script_verify_bit}),')
94+
script_verify_bit -= 1
95+
96+
defines["VERIFY_FLAGS_NAMES"].append(f'{{ "{dep}", SCRIPT_VERIFY_{dep} }},')
97+
98+
defines["STANDARD_VERIFY_FLAGS"].append(f'SCRIPT_VERIFY_{dep} |')
99+
100+
defines["CONSENSUS_CHECKS"].append(f'if (DeploymentActiveAt(block_index, chainman, Consensus::DEPLOYMENT_{dep})) flags |= SCRIPT_VERIFY_{dep};')
101+
102+
discourage = False
103+
if b.get("scriptverify", False) and b.get("scriptverify_discourage", False):
104+
discourage = True
105+
defines["VERIFY_FLAGS"].append(f'SCRIPT_VERIFY_DISCOURAGE_{dep} = (1U << {script_verify_bit}),')
106+
script_verify_bit -= 1
107+
108+
defines["VERIFY_FLAGS_NAMES"].append(f'{{ "DISCOURAGE_{dep}", SCRIPT_VERIFY_DISCOURAGE_{dep} }},')
109+
110+
defines["SCRIPTERR"].append(f'SCRIPT_ERR_DISCOURAGE_{dep},')
111+
defines["SCRIPTERR_STRING"].append(f'case SCRIPT_ERR_DISCOURAGE_{dep}: return "Reserved for {dep} soft-fork upgrade";')
112+
defines["SCRIPTERR_TEST_NAMES"].append('{ SCRIPT_ERR_DISCOURAGE_%s, "DISCOURAGE_%s" },' % (dep, dep))
113+
defines["POLICY_CHECKS"].append('{ Consensus::DEPLOYMENT_%s, SCRIPT_VERIFY_DISCOURAGE_%s },' % (dep, dep))
114+
115+
if "opcodes" in b:
116+
for opcodename, opcodehexstr in b["opcodes"].items():
117+
if opcodename not in DISABLED_OPCODES:
118+
defines["OPCODES"].append(f'OP_{opcodename} = {opcodehexstr},')
119+
defines["OPCODE_NAMES"].append(f'case OP_{opcodename}: return "OP_{opcodename}";')
120+
if discourage:
121+
defines["SUCCESS_OPCODES"].append(f'case OP_{opcodename}:')
122+
if discourage:
123+
defines["SUCCESS_OPCODES"].append(f' if (auto e = op_success_check(flags, SCRIPT_VERIFY_{dep}, SCRIPT_VERIFY_DISCOURAGE_{dep}, SCRIPT_ERR_DISCOURAGE_{dep}, serror)) return e; else break;')
124+
125+
header.write("// Automatically generated\n")
126+
header.write("#ifndef BINANA_H\n")
127+
header.write("#define BINANA_H\n\n")
128+
for d in defines:
129+
header.write(f'#define INQ_{d} \\\n')
130+
for l in defines[d]:
131+
header.write(f' {l} \\\n')
132+
header.write("\n\n")
133+
header.write("#endif // BINANA_H\n")
134+
135+
json.dump(jsoninfo, depjson, indent=2)
136+
137+
def gen_binana_d(data, out):
138+
deps = sorted(data[k]["filename"] for k in data)
139+
out.write("binana.h binana.d : %s\n" % (" ".join(deps)))
140+
141+
def main(argv):
142+
parser = argparse.ArgumentParser()
143+
parser.add_argument("defns")
144+
parser.add_argument("header")
145+
parser.add_argument("deploymentjson")
146+
args = parser.parse_args(argv)
147+
148+
data = get_binana_info(args.defns)
149+
with ConditionalWriter(args.header) as binana_h:
150+
with ConditionalWriter(args.deploymentjson) as binana_json:
151+
gen_binana_h(data, binana_h, binana_json)
152+
153+
#gen_binana_d(data, open("binana.d", "w", encoding="utf8"))
154+
155+
if __name__ == "__main__":
156+
main(sys.argv[1:])
157+

src/consensus/params.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef BITCOIN_CONSENSUS_PARAMS_H
77
#define BITCOIN_CONSENSUS_PARAMS_H
88

9+
#include <binana.h>
910
#include <uint256.h>
1011

1112
#include <array>
@@ -34,6 +35,7 @@ constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_
3435
enum DeploymentPos : uint16_t {
3536
DEPLOYMENT_TESTDUMMY,
3637
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
38+
INQ_DEPLOYMENTS
3739
MAX_VERSION_BITS_DEPLOYMENTS
3840
};
3941
constexpr bool ValidDeployment(DeploymentPos dep) { return dep < MAX_VERSION_BITS_DEPLOYMENTS; }

src/deploymentinfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <deploymentinfo.h>
66

7+
#include <binana.h>
78
#include <consensus/params.h>
89
#include <script/interpreter.h>
910
#include <tinyformat.h>
@@ -15,6 +16,7 @@ const std::array<VBDeploymentInfo,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> Versi
1516
.name = "testdummy",
1617
.gbt_force = true,
1718
},
19+
INQ_DEPLOYMENTS_GBT
1820
};
1921

2022
std::string DeploymentName(Consensus::BuriedDeployment dep)
@@ -76,6 +78,7 @@ const std::map<std::string, uint32_t> g_verify_flag_names{
7678
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
7779
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
7880
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
81+
INQ_VERIFY_FLAGS_NAMES
7982
};
8083
#undef FLAG_NAME
8184

src/kernel/chainparams.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <kernel/chainparams.h>
77

8+
#include <binana.h>
89
#include <chainparamsseeds.h>
910
#include <consensus/amount.h>
1011
#include <consensus/merkle.h>
@@ -143,7 +144,10 @@ class CMainParams : public CChainParams {
143144
consensus.fPowAllowMinDifficultyBlocks = false;
144145
consensus.enforce_BIP94 = false;
145146
consensus.fPowNoRetargeting = false;
146-
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
147+
148+
for (auto& dep : consensus.vDeployments) {
149+
dep = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
150+
}
147151

148152
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000b1f3b93b65b16d035a82be84"};
149153
consensus.defaultAssumeValid = uint256{"00000000000000000001b658dd1120e82e66d2790811f89ede9742ada3ed6d77"}; // 886157
@@ -265,6 +269,10 @@ class CTestNetParams : public CChainParams {
265269
consensus.fPowNoRetargeting = false;
266270
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
267271

272+
for (auto& dep : consensus.vDeployments) {
273+
dep = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
274+
}
275+
268276
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000015f5e0c9f13455b0eb17"};
269277
consensus.defaultAssumeValid = uint256{"00000000000003fc7967410ba2d0a8a8d50daedc318d43e8baf1a9782c236a57"}; // 3974606
270278

@@ -352,7 +360,10 @@ class CTestNet4Params : public CChainParams {
352360
consensus.fPowAllowMinDifficultyBlocks = true;
353361
consensus.enforce_BIP94 = true;
354362
consensus.fPowNoRetargeting = false;
355-
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
363+
364+
for (auto& dep : consensus.vDeployments) {
365+
dep = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 2016};
366+
}
356367

357368
consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000001d6dce8651b6094e4c1"};
358369
consensus.defaultAssumeValid = uint256{"0000000000003ed4f08dbdf6f7d6b271a6bcffce25675cb40aa9fa43179a89f3"}; // 72600
@@ -482,6 +493,7 @@ class SigNetParams : public CChainParams {
482493
consensus.powLimit = uint256{"00000377ae000000000000000000000000000000000000000000000000000000"};
483494

484495
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.activate = 0x30000000, .abandon = 0, .never = true, .period = 432};
496+
INQ_DEPLOYMENTS_SIGNET
485497

486498
RenounceDeployments(options.renounce, consensus.vDeployments);
487499

@@ -551,6 +563,7 @@ class CRegTestParams : public CChainParams
551563

552564
// 0x3000_0000 = bit 28 plus versionbits signalling; 0x5000_0000 = bit 38 plus VERSIONBITS_TOP_ABANDON
553565
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY] = SetupDeployment{.start = 0, .timeout = Consensus::HereticalDeployment::NO_TIMEOUT, .activate = 0x30000000, .abandon = 0x50000000, .period = 144};
566+
INQ_DEPLOYMENTS_REGTEST
554567

555568
consensus.nMinimumChainWork = uint256{};
556569
consensus.defaultAssumeValid = uint256{};

src/policy/policy.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef BITCOIN_POLICY_POLICY_H
77
#define BITCOIN_POLICY_POLICY_H
88

9+
#include <binana.h>
910
#include <consensus/amount.h>
1011
#include <consensus/consensus.h>
1112
#include <primitives/transaction.h>
@@ -123,7 +124,10 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
123124
SCRIPT_VERIFY_CONST_SCRIPTCODE |
124125
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
125126
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
126-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
127+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
128+
INQ_STANDARD_VERIFY_FLAGS
129+
0
130+
};
127131

128132
/** For convenience, standard but not mandatory verify flags. */
129133
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};

src/script/interpreter.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <script/interpreter.h>
77

8+
#include <binana.h>
89
#include <crypto/ripemd160.h>
910
#include <crypto/sha1.h>
1011
#include <crypto/sha256.h>
@@ -1786,6 +1787,13 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
17861787
template class GenericTransactionSignatureChecker<CTransaction>;
17871788
template class GenericTransactionSignatureChecker<CMutableTransaction>;
17881789

1790+
[[maybe_unused]] static std::optional<bool> op_success_check(unsigned int flags, unsigned int enforce, unsigned int discourage, ScriptError discourage_err, ScriptError* serror)
1791+
{
1792+
if (flags & discourage) return set_error(serror, discourage_err);
1793+
if (!(flags & enforce)) return set_success(serror);
1794+
return std::nullopt;
1795+
}
1796+
17891797
std::optional<bool> CheckTapscriptOpSuccess(const CScript& exec_script, unsigned int flags, ScriptError* serror)
17901798
{
17911799
{
@@ -1799,10 +1807,18 @@ std::optional<bool> CheckTapscriptOpSuccess(const CScript& exec_script, unsigned
17991807
}
18001808
// New opcodes will be listed here. May use a different sigversion to modify existing opcodes.
18011809
if (IsOpSuccess(opcode)) {
1802-
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1803-
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1810+
switch(opcode) {
1811+
INQ_SUCCESS_OPCODES
1812+
case OP_RESERVED:
1813+
// special case this to give an error if attempting to replace it,
1814+
// and to avoid MSVC++ error message about no case statements
1815+
[[fallthrough]];
1816+
default:
1817+
if (flags & SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS) {
1818+
return set_error(serror, SCRIPT_ERR_DISCOURAGE_OP_SUCCESS);
1819+
}
1820+
return set_success(serror);
18041821
}
1805-
return set_success(serror);
18061822
}
18071823
}
18081824
}

src/script/interpreter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef BITCOIN_SCRIPT_INTERPRETER_H
77
#define BITCOIN_SCRIPT_INTERPRETER_H
88

9+
#include <binana.h>
910
#include <consensus/amount.h>
1011
#include <hash.h>
1112
#include <primitives/transaction.h>
@@ -143,6 +144,8 @@ enum : uint32_t {
143144
// Making unknown public key versions (in BIP 342 scripts) non-standard
144145
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1U << 20),
145146

147+
INQ_VERIFY_FLAGS
148+
146149
// Constants to point to the highest flag in use. Add new flags above this line.
147150
//
148151
SCRIPT_VERIFY_END_MARKER

0 commit comments

Comments
 (0)