Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

/checkRBF.js Secret

Created November 29, 2015 10:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/b935887caec15849cb15 to your computer and use it in GitHub Desktop.
Save anonymous/b935887caec15849cb15 to your computer and use it in GitHub Desktop.
RBFのフラグが立っているかどうかをみるためのjavascript
// 普通のjavaScriptで、今度Bitcoin Coreに実装されるRBFの希望するためのフラグを読んで
// 生取引からそのフラグが立っているかどうかを返す isRBF の関数が入っています。
/**
* 生取引データの文字列を入れ、RBFのフラグが立っているかどうかを返す
* @param {string} rawtx 生取引データの文字列。例:"0100000001ae4d..."
* @return {bool} RBFのフラグが立っているかどうか
*/
function isRBF(rawtx) {
// nSequenceの値を配列で返す
var sequences = getSequenceValues(rawtx);
// nSequenceが全て 0xffffffff ならRBFじゃないので false を返す
for (var i = 0; i < sequences.length; i++) {
// 一個でも 0xffffffff じゃない nSequenceがあれば、RBFなので true
if (sequences[i] !== 0xffffffff) return true;
};
return false;
};
/**
* 生取引データの文字列を入れ、入力のnSequenceを全て返す
* @param {string} rawtx 生取引データの文字列。例:"0100000001ae4d..."
* @return {number[]} 各入力のnSequence値を配列に入れたもの
*/
function getSequenceValues(rawtx) {
//戻り値
var ret = [];
// バージョン番号トル
rawtx = rawtx.slice(8);
var input_count = readVarInt(rawtx);
var sigScriptLen;
// 入力数のVarIntトル
rawtx = rawtx.slice(input_count.length * 2);
for (var i = 0; i < input_count.value; i++) {
// 入力のtxOutHashとtxOutIndexトル
rawtx = rawtx.slice(64 + 8);
sigScriptLen = readVarInt(rawtx);
// 入力のvarIntとscriptSigトル
rawtx = rawtx.slice((sigScriptLen.length * 2) + (sigScriptLen.value * 2));
// 入力のnSequenceを配列に挿入
ret.push(parseInt(rawtx.slice(0, 8), 16));
// 入力のnSequenceトルと次の入力が先頭にくる
rawtx = rawtx.slice(8);
};
return ret;
};
/**
* varIntの値が先頭にある生取引の一部を入れて、varInt自体のバイト数と
* varIntの値をオブジェクトとして返す
* @param {string} hex varIntが先頭にある文字列。例:"fd02018c62..."
* @return {object} パラメータはlength : バイト数, value : 値
*/
function readVarInt(hex) {
// 1バイト以下はダメ
if (hex.length < 2) throw "VarInt must be at least 1 byte!";
// 頭のバイトが長さを教えてくれる。
var first = parseInt(hex.slice(0,2), 16);
var intval;
var intlen;
if (first < 0xfd) {
// 0xfd以下のものは1バイトの長さです。そのままが値になる。
intval = first;
intlen = 1;
} else if (first === 0xfd) {
if (hex.length < 6) throw "VarInt starting with 0xfd must be at least 3 bytes!";
// 0xfdのものは3バイトの長さです。残り2バイトはリトルエンディアンなので、バイトの順番を逆にする。
intval = parseInt(hex.slice(4,6) + hex.slice(2,4), 16);
intlen = 3;
} else if (first === 0xfe) {
if (hex.length < 10) throw "VarInt starting with 0xfe must be at least 5 bytes!";
// 0xfeのものは5バイトの長さです。残り4バイトはリトルエンディアンなので、バイトの順番を逆にする。
intval = parseInt(hex.slice(8,10) + hex.slice(6,8) + hex.slice(4,6) + hex.slice(2,4), 16);
intlen = 5;
} else if (first === 0xff) {
if (hex.length < 18) throw "VarInt starting with 0xff must be at least 9 bytes!";
// 0xffのものは9バイトの長さです。残り8バイトはリトルエンディアンなので、バイトの順番を逆にする。
intval = parseInt(hex.slice(16,18) + hex.slice(14,16) + hex.slice(12,14) + hex.slice(10,12) + hex.slice(8,10) + hex.slice(6,8) + hex.slice(4,6) + hex.slice(2,4), 16);
// javaScriptのparseIntに上限がある。この数字を超えるvarIntはビットコイン取引の中であり得ないのだが、念のため。
if (intval > 9007199254740991) throw "javascript parseInt does not support hex values over 0x1fffffffffffff";
intlen = 9;
};
return {length: intlen, value: intval};
};
@achow101
Copy link

if (sequences[i] !== 0xffffffff) return true;
is incorrect. The sequence number must be less than 0xfffffffd since 0xfffffffe does not signal RBF but does signal locktime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment