mirror of
https://github.com/Retropex/mempool.git
synced 2025-05-12 18:20:41 +02:00
Merge branch 'master' into natsoni/tx-preview-feedback
This commit is contained in:
commit
5c02670281
1
.github/workflows/on-tag.yml
vendored
1
.github/workflows/on-tag.yml
vendored
@ -105,7 +105,6 @@ jobs:
|
||||
--cache-to "type=local,dest=/tmp/.buildx-cache,mode=max" \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:$TAG \
|
||||
--tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:latest \
|
||||
--build-context rustgbt=./rust \
|
||||
--build-context backend=./backend \
|
||||
--output "type=registry,push=true" \
|
||||
|
@ -406,8 +406,8 @@ class BitcoinRoutes {
|
||||
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * cacheDuration).toUTCString());
|
||||
res.json(block);
|
||||
} catch (e) {
|
||||
handleError(req, res, 500, 'Failed to get block');
|
||||
} catch (e: any) {
|
||||
handleError(req, res, e?.response?.status === 404 ? 404 : 500, 'Failed to get block');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ const POLL_FREQUENCY = 5 * 60 * 1000; // 5 minutes
|
||||
class WalletApi {
|
||||
private wallets: Record<string, Wallet> = {};
|
||||
private syncing = false;
|
||||
private lastSync = 0;
|
||||
|
||||
constructor() {
|
||||
this.wallets = config.WALLETS.ENABLED ? (config.WALLETS.WALLETS as string[]).reduce((acc, wallet) => {
|
||||
@ -47,7 +48,38 @@ class WalletApi {
|
||||
if (!config.WALLETS.ENABLED || this.syncing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncing = true;
|
||||
|
||||
if (config.WALLETS.AUTO && (Date.now() - this.lastSync) > POLL_FREQUENCY) {
|
||||
try {
|
||||
// update list of active wallets
|
||||
this.lastSync = Date.now();
|
||||
const response = await axios.get(config.MEMPOOL_SERVICES.API + `/wallets`);
|
||||
const walletList: string[] = response.data;
|
||||
if (walletList) {
|
||||
// create a quick lookup dictionary of active wallets
|
||||
const newWallets: Record<string, boolean> = Object.fromEntries(
|
||||
walletList.map(wallet => [wallet, true])
|
||||
);
|
||||
for (const wallet of walletList) {
|
||||
// don't overwrite existing wallets
|
||||
if (!this.wallets[wallet]) {
|
||||
this.wallets[wallet] = { name: wallet, addresses: {}, lastPoll: 0 };
|
||||
}
|
||||
}
|
||||
// remove wallets that are no longer active
|
||||
for (const wallet of Object.keys(this.wallets)) {
|
||||
if (!newWallets[wallet]) {
|
||||
delete this.wallets[wallet];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logger.err(`Error updating active wallets: ${(e instanceof Error ? e.message : e)}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const walletKey of Object.keys(this.wallets)) {
|
||||
const wallet = this.wallets[walletKey];
|
||||
if (wallet.lastPoll < (Date.now() - POLL_FREQUENCY)) {
|
||||
@ -72,6 +104,7 @@ class WalletApi {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.syncing = false;
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@ interface IConfig {
|
||||
},
|
||||
WALLETS: {
|
||||
ENABLED: boolean;
|
||||
AUTO: boolean;
|
||||
WALLETS: string[];
|
||||
},
|
||||
STRATUM: {
|
||||
@ -334,6 +335,7 @@ const defaults: IConfig = {
|
||||
},
|
||||
'WALLETS': {
|
||||
'ENABLED': false,
|
||||
'AUTO': false,
|
||||
'WALLETS': [],
|
||||
},
|
||||
'STRATUM': {
|
||||
|
@ -16,10 +16,10 @@
|
||||
"mobileOrder": 4
|
||||
},
|
||||
{
|
||||
"component": "balance",
|
||||
"component": "walletBalance",
|
||||
"mobileOrder": 1,
|
||||
"props": {
|
||||
"address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo"
|
||||
"wallet": "ONBTC"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -30,21 +30,22 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "address",
|
||||
"component": "wallet",
|
||||
"mobileOrder": 2,
|
||||
"props": {
|
||||
"address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo",
|
||||
"period": "1m"
|
||||
"wallet": "ONBTC",
|
||||
"period": "1m",
|
||||
"label": "bitcoin.gob.sv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "blocks"
|
||||
},
|
||||
{
|
||||
"component": "addressTransactions",
|
||||
"component": "walletTransactions",
|
||||
"mobileOrder": 3,
|
||||
"props": {
|
||||
"address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo"
|
||||
"wallet": "ONBTC"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -256,6 +256,11 @@ export function detectScriptTemplate(type: ScriptType, script_asm: string, witne
|
||||
return ScriptTemplates.multisig(tapscriptMultisig.m, tapscriptMultisig.n);
|
||||
}
|
||||
|
||||
const tapscriptUnanimousMultisig = parseTapscriptUnanimousMultisig(script_asm);
|
||||
if (tapscriptUnanimousMultisig) {
|
||||
return ScriptTemplates.multisig(tapscriptUnanimousMultisig, tapscriptUnanimousMultisig);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -310,11 +315,13 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
|
||||
}
|
||||
|
||||
const ops = script.split(' ');
|
||||
// At minimum, one pubkey group (3 tokens) + m push + final opcode = 5 tokens
|
||||
if (ops.length < 5) return;
|
||||
// At minimum, 2 pubkey group (3 tokens) + m push + final opcode = 8 tokens
|
||||
if (ops.length < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
const finalOp = ops.pop();
|
||||
if (finalOp !== 'OP_NUMEQUAL' && finalOp !== 'OP_GREATERTHANOREQUAL') {
|
||||
if (!['OP_NUMEQUAL', 'OP_NUMEQUALVERIFY', 'OP_GREATERTHANOREQUAL', 'OP_GREATERTHAN', 'OP_EQUAL', 'OP_EQUALVERIFY'].includes(finalOp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -329,6 +336,10 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
|
||||
return;
|
||||
}
|
||||
|
||||
if (finalOp === 'OP_GREATERTHAN') {
|
||||
m += 1;
|
||||
}
|
||||
|
||||
if (ops.length % 3 !== 0) {
|
||||
return;
|
||||
}
|
||||
@ -360,6 +371,53 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
|
||||
return { m, n };
|
||||
}
|
||||
|
||||
export function parseTapscriptUnanimousMultisig(script: string): undefined | number {
|
||||
if (!script) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ops = script.split(' ');
|
||||
// At minimum, 2 pubkey group (3 tokens) = 6 tokens
|
||||
if (ops.length < 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ops.length % 3 !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const n = ops.length / 3;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const pushOp = ops.shift();
|
||||
const pubkey = ops.shift();
|
||||
const sigOp = ops.shift();
|
||||
|
||||
if (pushOp !== 'OP_PUSHBYTES_32') {
|
||||
return;
|
||||
}
|
||||
if (!/^[0-9a-fA-F]{64}$/.test(pubkey)) {
|
||||
return;
|
||||
}
|
||||
if (i < n - 1) {
|
||||
if (sigOp !== 'OP_CHECKSIGVERIFY') {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Last opcode can be either CHECKSIG or CHECKSIGVERIFY
|
||||
if (!(sigOp === 'OP_CHECKSIGVERIFY' || sigOp === 'OP_CHECKSIG')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ops.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
export function getVarIntLength(n: number): number {
|
||||
if (n < 0xfd) {
|
||||
return 1;
|
||||
|
@ -1,7 +1,16 @@
|
||||
@reboot sleep 5 ; /usr/local/bin/bitcoind -testnet >/dev/null 2>&1
|
||||
@reboot sleep 5 ; /usr/local/bin/bitcoind -testnet4 >/dev/null 2>&1
|
||||
@reboot sleep 5 ; /usr/local/bin/bitcoind -signet >/dev/null 2>&1
|
||||
@reboot sleep 10 ; screen -dmS mainnet /bitcoin/electrs/start mainnet
|
||||
@reboot sleep 10 ; screen -dmS testnet /bitcoin/electrs/start testnet
|
||||
@reboot sleep 10 ; screen -dmS testnet4 /bitcoin/electrs/start testnet4
|
||||
@reboot sleep 10 ; screen -dmS signet /bitcoin/electrs/start signet
|
||||
# start test network daemons on boot
|
||||
@reboot sleep 10 ; /usr/local/bin/bitcoind -testnet >/dev/null 2>&1
|
||||
@reboot sleep 20 ; /usr/local/bin/bitcoind -testnet4 >/dev/null 2>&1
|
||||
@reboot sleep 30 ; /usr/local/bin/bitcoind -signet >/dev/null 2>&1
|
||||
|
||||
# start electrs on boot
|
||||
@reboot sleep 40 ; screen -dmS mainnet /bitcoin/electrs/start mainnet
|
||||
@reboot sleep 50 ; screen -dmS testnet /bitcoin/electrs/start testnet
|
||||
@reboot sleep 60 ; screen -dmS testnet4 /bitcoin/electrs/start testnet4
|
||||
@reboot sleep 70 ; screen -dmS signet /bitcoin/electrs/start signet
|
||||
|
||||
# daily update of popular-scripts
|
||||
30 03 * * * $HOME/electrs/start testnet4 popular-scripts >/dev/null 2>&1
|
||||
31 03 * * * $HOME/electrs/start testnet popular-scripts >/dev/null 2>&1
|
||||
32 03 * * * $HOME/electrs/start signet popular-scripts >/dev/null 2>&1
|
||||
33 03 * * * $HOME/electrs/start mainnet popular-scripts >/dev/null 2>&1
|
||||
|
@ -8,3 +8,7 @@
|
||||
|
||||
# hourly asset update and electrs restart
|
||||
6 * * * * cd $HOME/asset_registry_db && git pull --quiet origin master && cd $HOME/asset_registry_testnet_db && git pull --quiet origin master && killall electrs
|
||||
|
||||
# daily update of popular-scripts
|
||||
32 03 * * * $HOME/electrs/start liquid popular-scripts >/dev/null 2>&1
|
||||
33 03 * * * $HOME/electrs/start liquidtestnet popular-scripts >/dev/null 2>&1
|
||||
|
@ -159,6 +159,7 @@
|
||||
},
|
||||
"WALLETS": {
|
||||
"ENABLED": true,
|
||||
"AUTO": true,
|
||||
"WALLETS": ["BITB", "3350"]
|
||||
},
|
||||
"STRATUM": {
|
||||
|
@ -4,7 +4,7 @@ hostname=$(hostname)
|
||||
heat()
|
||||
{
|
||||
echo "$1"
|
||||
curl -i -s "$1" | head -1
|
||||
curl -o /dev/null -s "$1"
|
||||
}
|
||||
|
||||
heatURLs=(
|
||||
|
@ -6,19 +6,19 @@ slugs=(`curl -sSL https://${hostname}/api/v1/mining/pools/3y|jq -r -S '(.pools[]
|
||||
warmSlurp()
|
||||
{
|
||||
echo "$1"
|
||||
curl -i -s -H 'User-Agent: Googlebot' "$1" | head -1
|
||||
curl -o /dev/null -s -H 'User-Agent: Googlebot' "$1"
|
||||
}
|
||||
|
||||
warmUnfurl()
|
||||
{
|
||||
echo "$1"
|
||||
curl -i -s -H 'User-Agent: Twitterbot' "$1" | head -1
|
||||
curl -o /dev/null -s -H 'User-Agent: Twitterbot' "$1"
|
||||
}
|
||||
|
||||
warm()
|
||||
{
|
||||
echo "$1"
|
||||
curl -i -s "$1" | head -1
|
||||
curl -o /dev/null -s "$1"
|
||||
}
|
||||
|
||||
warmSlurpURLs=(
|
||||
|
Loading…
Reference in New Issue
Block a user