(4) 블록 체인 데이터 구조 – 스 크 립 트
누 군가 에 게 비트 코 인 을 지불 할 때 우 리 는 거래 입력 에 잠 금 해제 스 크 립 트 를 설정 하고 다른 사람 에 게 우리 가 이 입력 을 최선 을 다 하고 있다 는 것 을 증명 해 야 한다. 또한 우 리 는 거래 출력 에 잠 금 스 크 립 트 를 추가 하여 수신 자 만 이 출력 을 잠 금 해제 할 수 있 도록 해 야 한다.
각본
비트 코 인 시스템 은 잠 금, 잠 금 해제 와 같은 스 크 립 트 언어 를 전문 적 으로 설계 하 였 으 나 이러한 조작 에 국한 되 지 않 습 니 다.이 스 크 립 트 언어 는 스 택 에 기반 한 해석 형 언어 입 니 다.
예 를 들 어 스 크 립 트: 23 ADD 5 EQUAL, 이 스 크 립 트 의 실행 과정 은 다음 과 같다.
실현 부분 에서 스 크 립 트 는 여러 개의 조작 단원 으로 구성 되 는데 이 단원 들 은 데이터 단원 일 수도 있 고 계산 단원 일 수도 있다.상기 사례 는 2, 3, 5 는 데이터 유닛, ADD, EQUAL 은 계산 유닛 이다.따라서 스 크 립 트 23 ADD 5 EQUAL 은 5 개의 조작 단위 로 봉 인 됩 니 다.
스 크 립 트 의 논리 구 조 는 다음 과 같 습 니 다 (인 스 턴 스).
핵심 코드 - 변수 정의
// The program is a set of chunks where each element is either [opcode] or [data, data, data ...]
// 。 ,
protected List chunks;
// Unfortunately, scripts are not ever re-serialized or canonicalized when used in signature hashing. Thus we
// must preserve the exact bytes that we read off the wire, along with the parsed form.
// ( , )
protected byte[] program;
핵심 코드 - 데이터 분석
// , :
// (OP_DUP), HASH160 (OP_HASH160)、
// (OP_EQUALVERIFY)、 (OP_CHECKSIG)
private static final ScriptChunk[] STANDARD_TRANSACTION_SCRIPT_CHUNKS = {
new ScriptChunk(ScriptOpCodes.OP_DUP, null, 0),
new ScriptChunk(ScriptOpCodes.OP_HASH160, null, 1),
new ScriptChunk(ScriptOpCodes.OP_EQUALVERIFY, null, 23),
new ScriptChunk(ScriptOpCodes.OP_CHECKSIG, null, 24),
};
/**
* ,
* To run a script, first we parse it which breaks it up into chunks representing pushes of data or logical
* opcodes. Then we can run the parsed chunks.
* , , 。 。
*
* The reason for this split, instead of just interpreting directly, is to make it easier
* to reach into a programs structure and pull out bits of data without having to run it.
* This is necessary to render the to/from addresses of transactions in a user interface.
* Bitcoin Core does something similar.
* , , , 。
*/
private void parse(byte[] program) throws ScriptException {
// , 5, 5
chunks = new ArrayList<>(5); // Common size.
ByteArrayInputStream bis = new ByteArrayInputStream(program);
int initialSize = bis.available();
while (bis.available() > 0) {
//
int startLocationInProgram = initialSize - bis.available();
int opcode = bis.read(); //
long dataToRead = -1; //
// OP_PUSHDATA1, dataToRead
// OP_PUSHDATA1, ,
// OP_PUSHDATA2, ,
// OP_PUSHDATA4, ,
//
if (opcode >= 0 && opcode < OP_PUSHDATA1) {
// Read some bytes of data, where how many is the opcode value itself.
dataToRead = opcode;
} else if (opcode == OP_PUSHDATA1) {
if (bis.available() < 1) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
dataToRead = bis.read();
} else if (opcode == OP_PUSHDATA2) {
// Read a short, then read that many bytes of data.
if (bis.available() < 2) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
dataToRead = Utils.readUint16FromStream(bis);
} else if (opcode == OP_PUSHDATA4) {
// Read a uint32, then read that many bytes of data.
// Though this is allowed, because its value cannot be > 520, it should never actually be used
if (bis.available() < 4) throw new ScriptException(ScriptError.SCRIPT_ERR_UNKNOWN_ERROR, "Unexpected end of script");
dataToRead = Utils.readUint32FromStream(bis);
}
ScriptChunk chunk;
// -1, ,
// -1,
if (dataToRead == -1) {
chunk = new ScriptChunk(opcode, null, startLocationInProgram);
} else {
if (dataToRead > bis.available())
throw new ScriptException(ScriptError.SCRIPT_ERR_BAD_OPCODE, "Push of data element that is larger than remaining data");
byte[] data = new byte[(int)dataToRead];
//
checkState(dataToRead == 0 || bis.read(data, 0, (int)dataToRead) == dataToRead);
chunk = new ScriptChunk(opcode, data, startLocationInProgram);
}
// Save some memory by eliminating redundant copies of the same chunk objects.
// , ( , , )
for (ScriptChunk c : STANDARD_TRANSACTION_SCRIPT_CHUNKS) {
if (c.equals(chunk)) chunk = c;
}
//
chunks.add(chunk);
}
}
조작 단위
조작 단원 은 데이터 단원 과 연산 단원 으로 나 뉜 다.연산 단원 은 데 이 터 를 창고 에 넣 는 데 사용 되 며, 추 후 연산 을 진행 합 니 다 - 연산 단원 은 창고 에서 데 이 터 를 꺼 내 고 연산 을 진행 하 며, 연산 결 과 를 창고 에 넣 습 니 다
조작 단원 의 논리 구 조 는 다음 과 같다.
핵심 코드 - 변수 정의
/** Operation to be executed. Opcodes are defined in {@link ScriptOpCodes}. */
public final int opcode; // , , ScriptOpCodes
/**
* For push operations, this is the vector to be pushed on the stack. For {@link ScriptOpCodes#OP_0}, the vector is
* empty. Null for non-push operations.
* , , ,
*/
@Nullable
public final byte[] data;
private int startLocationInProgram; //
핵심 코드 - 조작 부호
// push value
public static final int OP_0 = 0x00; // push empty vector ( )
// ,
public static final int OP_FALSE = OP_0;
public static final int OP_PUSHDATA1 = 0x4c;
public static final int OP_PUSHDATA2 = 0x4d;
public static final int OP_PUSHDATA4 = 0x4e;
public static final int OP_1NEGATE = 0x4f;
public static final int OP_RESERVED = 0x50;
public static final int OP_1 = 0x51;
public static final int OP_TRUE = OP_1;
public static final int OP_2 = 0x52;
public static final int OP_3 = 0x53;
public static final int OP_4 = 0x54;
public static final int OP_5 = 0x55;
public static final int OP_6 = 0x56;
public static final int OP_7 = 0x57;
public static final int OP_8 = 0x58;
public static final int OP_9 = 0x59;
public static final int OP_10 = 0x5a;
public static final int OP_11 = 0x5b;
public static final int OP_12 = 0x5c;
public static final int OP_13 = 0x5d;
public static final int OP_14 = 0x5e;
public static final int OP_15 = 0x5f;
public static final int OP_16 = 0x60;
// control ,IF、ELSE
public static final int OP_NOP = 0x61;
public static final int OP_VER = 0x62;
public static final int OP_IF = 0x63;
public static final int OP_NOTIF = 0x64;
public static final int OP_VERIF = 0x65;
public static final int OP_VERNOTIF = 0x66;
public static final int OP_ELSE = 0x67;
public static final int OP_ENDIF = 0x68;
public static final int OP_VERIFY = 0x69;
public static final int OP_RETURN = 0x6a;
// stack ops 、
public static final int OP_TOALTSTACK = 0x6b;
public static final int OP_FROMALTSTACK = 0x6c;
public static final int OP_2DROP = 0x6d;
public static final int OP_2DUP = 0x6e;
public static final int OP_3DUP = 0x6f;
public static final int OP_2OVER = 0x70;
public static final int OP_2ROT = 0x71;
public static final int OP_2SWAP = 0x72;
public static final int OP_IFDUP = 0x73;
public static final int OP_DEPTH = 0x74;
public static final int OP_DROP = 0x75;
public static final int OP_DUP = 0x76;
public static final int OP_NIP = 0x77;
public static final int OP_OVER = 0x78;
public static final int OP_PICK = 0x79;
public static final int OP_ROLL = 0x7a;
public static final int OP_ROT = 0x7b;
public static final int OP_SWAP = 0x7c;
public static final int OP_TUCK = 0x7d;
// splice ops
public static final int OP_CAT = 0x7e;
public static final int OP_SUBSTR = 0x7f;
public static final int OP_LEFT = 0x80;
public static final int OP_RIGHT = 0x81;
public static final int OP_SIZE = 0x82;
// bit logic
public static final int OP_INVERT = 0x83;
public static final int OP_AND = 0x84;
public static final int OP_OR = 0x85;
public static final int OP_XOR = 0x86;
public static final int OP_EQUAL = 0x87;
public static final int OP_EQUALVERIFY = 0x88;
public static final int OP_RESERVED1 = 0x89;
public static final int OP_RESERVED2 = 0x8a;
// numeric
public static final int OP_1ADD = 0x8b;
public static final int OP_1SUB = 0x8c;
public static final int OP_2MUL = 0x8d;
public static final int OP_2DIV = 0x8e;
public static final int OP_NEGATE = 0x8f;
public static final int OP_ABS = 0x90;
public static final int OP_NOT = 0x91;
public static final int OP_0NOTEQUAL = 0x92;
public static final int OP_ADD = 0x93;
public static final int OP_SUB = 0x94;
public static final int OP_MUL = 0x95;
public static final int OP_DIV = 0x96;
public static final int OP_MOD = 0x97;
public static final int OP_LSHIFT = 0x98;
public static final int OP_RSHIFT = 0x99;
public static final int OP_BOOLAND = 0x9a;
public static final int OP_BOOLOR = 0x9b;
public static final int OP_NUMEQUAL = 0x9c;
public static final int OP_NUMEQUALVERIFY = 0x9d;
public static final int OP_NUMNOTEQUAL = 0x9e;
public static final int OP_LESSTHAN = 0x9f;
public static final int OP_GREATERTHAN = 0xa0;
public static final int OP_LESSTHANOREQUAL = 0xa1;
public static final int OP_GREATERTHANOREQUAL = 0xa2;
public static final int OP_MIN = 0xa3;
public static final int OP_MAX = 0xa4;
public static final int OP_WITHIN = 0xa5;
// crypto
public static final int OP_RIPEMD160 = 0xa6;
public static final int OP_SHA1 = 0xa7;
public static final int OP_SHA256 = 0xa8;
public static final int OP_HASH160 = 0xa9;
public static final int OP_HASH256 = 0xaa;
public static final int OP_CODESEPARATOR = 0xab;
public static final int OP_CHECKSIG = 0xac;
public static final int OP_CHECKSIGVERIFY = 0xad;
public static final int OP_CHECKMULTISIG = 0xae;
public static final int OP_CHECKMULTISIGVERIFY = 0xaf;
// block state
/** Check lock time of the block. Introduced in BIP 65, replacing OP_NOP2 */
public static final int OP_CHECKLOCKTIMEVERIFY = 0xb1;
public static final int OP_CHECKSEQUENCEVERIFY = 0xb2;
// expansion
public static final int OP_NOP1 = 0xb0;
:( ) –
: – Secp256k1
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ERC 20 - 분석 입력 데이터 자바 (transfer)maven 도입 문제. https://github.com/web3j/web3j/issues/489 다른 유사 성 은 당연히 abi json 을 미리 알 아야 한다....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.