Page MenuHomePhabricator

D14210.diff
No OneTemporary

D14210.diff

diff --git a/apps/ecash-herald/src/parse.js b/apps/ecash-herald/src/parse.js
--- a/apps/ecash-herald/src/parse.js
+++ b/apps/ecash-herald/src/parse.js
@@ -455,17 +455,26 @@
// Cashtab allows sending a cashtab msg with an airdrop
// These look like
// <prefix> <tokenId> <cashtabMsgPrefix> <msg>
-
- tokenId = stackArray[1];
+ if (stackArray.length >= 2 && stackArray[1].length === 64) {
+ tokenId = stackArray[1];
+ }
break;
}
case opReturn.knownApps.cashtabMsg.prefix: {
app = opReturn.knownApps.cashtabMsg.app;
// For a Cashtab msg, the next push on the stack is the Cashtab msg
// Cashtab msgs use utf8 encoding
- msg = prepareStringForTelegramHTML(
- Buffer.from(stackArray[1], 'hex').toString('utf8'),
- );
+
+ // Valid Cashtab Msg
+ // <protocol identifier> <msg in utf8>
+ msg =
+ stackArray.length >= 2
+ ? prepareStringForTelegramHTML(
+ Buffer.from(stackArray[1], 'hex').toString(
+ 'utf8',
+ ),
+ )
+ : `Invalid ${app}`;
break;
}
case opReturn.knownApps.cashtabMsgEncrypted.prefix: {
@@ -495,7 +504,12 @@
app = opReturn.knownApps.swap.app;
msg = '';
- if (stackArray[1] === '01' && stackArray[2] === '01') {
+ if (
+ stackArray.length >= 3 &&
+ stackArray[1] === '01' &&
+ stackArray[2] === '01' &&
+ stackArray[3].length === 64
+ ) {
// If this is a signal for buy or sell of a token, save the token id
// Ref https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
// A buy or sell signal tx will have '01' at stackArray[1] and stackArray[2] and
@@ -894,6 +908,11 @@
// stackArray for an airdrop tx will be
// [airdrop_protocol_identifier, airdropped_tokenId, optional_cashtab_msg_protocol_identifier, optional_cashtab_msg]
+ // Validate expected format
+ if (stackArray.length < 2 || stackArray[1].length !== 64) {
+ return `Invalid ${opReturn.knownApps.airdrop.app}`;
+ }
+
// get tokenId
const tokenId = stackArray[1];
@@ -945,6 +964,12 @@
// Intialize msg
let msg = '';
+ // Generic validation to handle possible txs with SWaP protocol identifier but unexpected stack
+ if (stackArray.length < 3) {
+ // If stackArray[1] and stackArray[2] do not exist
+ return 'Invalid SWaP';
+ }
+
// SWaP txs are complex. Parse stackArray to build msg.
// https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md
@@ -987,9 +1012,17 @@
msg += '|';
} else {
// Note: tokenInfo is false if the API call to chronik fails
- // Link to token id
- msg += `<a href="${config.blockExplorer}/tx/${stackArray[3]}">Unknown Token</a>`;
- msg += '|';
+ // Also false if tokenId is invalid for some reason
+ // Link to token id if valid
+ if (
+ stackArray.length >= 3 &&
+ stackArray[3].length === 64
+ ) {
+ msg += `<a href="${config.blockExplorer}/tx/${stackArray[3]}">Unknown Token</a>`;
+ msg += '|';
+ } else {
+ msg += 'Invalid tokenId|';
+ }
}
// buy or sell?
@@ -1060,7 +1093,7 @@
}
default: {
// Malformed SWaP tx
- msg += 'Malformed SWaP tx';
+ msg += 'Invalid SWaP';
break;
}
}
@@ -1085,13 +1118,13 @@
}
default: {
// Malformed SWaP tx
- msg += 'Malformed SWaP tx';
+ msg += 'Invalid SWaP';
break;
}
}
} else {
// Malformed SWaP tx
- msg += 'Malformed SWaP tx';
+ msg += 'Invalid SWaP';
}
return msg;
},
diff --git a/apps/ecash-herald/test/mocks/appTxSamples.js b/apps/ecash-herald/test/mocks/appTxSamples.js
--- a/apps/ecash-herald/test/mocks/appTxSamples.js
+++ b/apps/ecash-herald/test/mocks/appTxSamples.js
@@ -147,7 +147,7 @@
// Malformed swap
{
hex: '045357500001010105204de69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf0453454c4c02025801002090dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f801010100',
- msg: 'Signal|Malformed SWaP tx',
+ msg: 'Signal|Invalid SWaP',
stackArray: [
'53575000',
'01',
@@ -163,6 +163,33 @@
tokenId: false,
tokenInfo: { tokenTicker: 'SPICE' },
},
+ // Mod 0101 https://explorer.e.cash/tx/b03883ca0b106ea5e7113d6cbe46b9ec37ac6ba437214283de2d9cf2fbdc997f
+ {
+ hex: '0453575000',
+ msg: 'Invalid SWaP',
+ stackArray: ['53575000'],
+ tokenId: false,
+ tokenInfo: false,
+ },
+ // Mod 0101 with bad tokenId
+ {
+ hex: '0453575000010101011fe69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf0453454c4c02025801002090dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f801010100',
+ msg: 'Signal|SLP Atomic Swap|Invalid tokenId|SELL for 6 XEC|Min trade: 0 XEC',
+ stackArray: [
+ '53575000',
+ '01',
+ '01',
+ 'e69e374a8ed21cbddd47f2338cc0f479dc58daa2bbe11cd604ca488eca0ddf', // 63 char, invalid tokenId
+ '53454c4c',
+ '0258',
+ '00',
+ '90dfb75fef5f07e384df4703b853a2741b8e6f3ef31ef8e5187a17fb107547f8',
+ '01',
+ '00',
+ ],
+ tokenId: false,
+ tokenInfo: false,
+ },
],
airdrops: [
// With a cashtab msg, non-empp
@@ -250,6 +277,77 @@
msgApiFailure:
'qrm...r48 airdropped 50 XEC to 4 holders of <a href="https://explorer.e.cash/tx/1c6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e">1c6...f5e</a>',
},
+ // Token id is not 64 char
+ {
+ txid: 'mod of 4403b0cc00ca159b64f219a7cc7cccd2e4440ddecbbcb6a0b82e78e350f8f72e',
+ hex: '0464726f701f6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
+ stackArray: [
+ '64726f70',
+ '6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e', // 63 chars
+ '00746162', // prefix for msg is there but no msg
+ ],
+ airdropSendingAddress:
+ 'ecash:qrmz0egsqxj35x5jmzf8szrszdeu72fx0uxgwk3r48',
+ airdropRecipientsKeyValueArray: [
+ [
+ '6a0464726f701f6c9c64d70b285befe733f175d0f384538576876bd280b10587df81279d3f5e0400746162',
+ 0,
+ ],
+ ['76a9147ab07df481649eb27c7ad9afda52b2a93d2f722a88ac', 2000],
+ ['76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac', 1000],
+ ['76a914b82361c5851f4ec48b995175a2e1c3646338e07688ac', 2000],
+ ],
+ tokenId: false,
+ tokenInfo: false,
+ coingeckoPrices: [
+ { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
+ { fiat: 'usd', price: 25000, ticker: 'BTC' },
+ { fiat: 'usd', price: 1900, ticker: 'ETH' },
+ ],
+ msg: 'Invalid Airdrop',
+ msgApiFailure: 'Invalid Airdrop',
+ },
+ // No stackArray[1]
+ {
+ txid: 'mod of 4403b0cc00ca159b64f219a7cc7cccd2e4440ddecbbcb6a0b82e78e350f8f72e',
+ hex: '0464726f70',
+ stackArray: ['64726f70'],
+ airdropSendingAddress:
+ 'ecash:qrmz0egsqxj35x5jmzf8szrszdeu72fx0uxgwk3r48',
+ airdropRecipientsKeyValueArray: [
+ ['6a0464726f70', 0],
+ ['76a9147ab07df481649eb27c7ad9afda52b2a93d2f722a88ac', 2000],
+ ['76a9149846b6b38ff713334ac19fe3cf851a1f98c07b0088ac', 1000],
+ ['76a914b82361c5851f4ec48b995175a2e1c3646338e07688ac', 2000],
+ ],
+ tokenId: false,
+ tokenInfo: false,
+ coingeckoPrices: [
+ { fiat: 'usd', price: 0.00003333, ticker: 'XEC' },
+ { fiat: 'usd', price: 25000, ticker: 'BTC' },
+ { fiat: 'usd', price: 1900, ticker: 'ETH' },
+ ],
+ msg: 'Invalid Airdrop',
+ msgApiFailure: 'Invalid Airdrop',
+ },
+ ],
+ cashtabMsgs: [
+ {
+ txid: 'b9c95c8cb8436be0574946071932aed3b82e5a8631d4de7a64ea29f7fba84759',
+ hex: '04007461623165436173684461793a2058454346617563657420546f70757020666f722045617374657220456767206769766561776179',
+ stackArray: [
+ '00746162',
+ '65436173684461793a2058454346617563657420546f70757020666f722045617374657220456767206769766561776179',
+ ],
+ msg: 'eCashDay: XECFaucet Topup for Easter Egg giveaway',
+ },
+ // no stackArray[1]
+ {
+ txid: 'N/A, mod of b9c95c8cb8436be0574946071932aed3b82e5a8631d4de7a64ea29f7fba84759',
+ hex: '0400746162',
+ stackArray: ['00746162'],
+ msg: 'Invalid Cashtab Msg',
+ },
],
encryptedCashtabMsgs: [
{
diff --git a/apps/ecash-herald/test/parseTests.js b/apps/ecash-herald/test/parseTests.js
--- a/apps/ecash-herald/test/parseTests.js
+++ b/apps/ecash-herald/test/parseTests.js
@@ -33,6 +33,7 @@
slp2PushVectors,
slp2TxVectors,
aliasRegistrations,
+ cashtabMsgs,
} = require('./mocks/appTxSamples');
describe('parse.js functions', function () {
@@ -88,6 +89,17 @@
});
}
});
+ it('parseOpReturn handles Cashtab Msgs', function () {
+ for (let i = 0; i < cashtabMsgs.length; i += 1) {
+ const { hex, stackArray, msg } = cashtabMsgs[i];
+ assert.deepEqual(parseOpReturn(hex), {
+ app: opReturn.knownApps.cashtabMsg.app,
+ msg,
+ stackArray,
+ tokenId: false,
+ });
+ }
+ });
it('parseOpReturn handles airdrop txs with and without a cashtab msg', function () {
for (let i = 0; i < airdrops.length; i += 1) {
const { hex, stackArray, tokenId } = airdrops[i];

File Metadata

Mime Type
text/plain
Expires
Tue, May 20, 20:43 (9 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5865910
Default Alt Text
D14210.diff (11 KB)

Event Timeline