From 1cd648d7842a04376ce45765c0d5e4415be41b9b Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Fri, 16 Feb 2018 16:18:43 -0500 Subject: [PATCH] Require atomic swap contracts to specify the secret size. This allows redeeming parties to audit the secret size and ensure it will be usable once revealed. --- txscript/standard.go | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 2ba5c8d9..a7e929d1 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -629,6 +629,7 @@ type AtomicSwapDataPushes struct { RecipientHash160 [20]byte RefundHash160 [20]byte SecretHash [32]byte + SecretSize int64 LockTime int64 } @@ -643,47 +644,61 @@ type AtomicSwapDataPushes struct { // // This function is only defined in the txscript package due to API limitations // which prevent callers using txscript to parse nonstandard scripts. -func ExtractAtomicSwapDataPushes(pkScript []byte) (*AtomicSwapDataPushes, error) { +func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error) { pops, err := parseScript(pkScript) if err != nil { return nil, err } - if len(pops) != 17 { + if len(pops) != 20 { return nil, nil } isAtomicSwap := pops[0].opcode.value == OP_IF && - pops[1].opcode.value == OP_SHA256 && - pops[2].opcode.value == OP_DATA_32 && + pops[1].opcode.value == OP_SIZE && + canonicalPush(pops[2]) && pops[3].opcode.value == OP_EQUALVERIFY && - pops[4].opcode.value == OP_DUP && - pops[5].opcode.value == OP_HASH160 && - pops[6].opcode.value == OP_DATA_20 && - pops[7].opcode.value == OP_ELSE && - canonicalPush(pops[8]) && - pops[9].opcode.value == OP_CHECKLOCKTIMEVERIFY && - pops[10].opcode.value == OP_DROP && - pops[11].opcode.value == OP_DUP && - pops[12].opcode.value == OP_HASH160 && - pops[13].opcode.value == OP_DATA_20 && - pops[14].opcode.value == OP_ENDIF && - pops[15].opcode.value == OP_EQUALVERIFY && - pops[16].opcode.value == OP_CHECKSIG + pops[4].opcode.value == OP_SHA256 && + pops[5].opcode.value == OP_DATA_32 && + pops[6].opcode.value == OP_EQUALVERIFY && + pops[7].opcode.value == OP_DUP && + pops[8].opcode.value == OP_HASH160 && + pops[9].opcode.value == OP_DATA_20 && + pops[10].opcode.value == OP_ELSE && + canonicalPush(pops[11]) && + pops[12].opcode.value == OP_CHECKLOCKTIMEVERIFY && + pops[13].opcode.value == OP_DROP && + pops[14].opcode.value == OP_DUP && + pops[15].opcode.value == OP_HASH160 && + pops[16].opcode.value == OP_DATA_20 && + pops[17].opcode.value == OP_ENDIF && + pops[18].opcode.value == OP_EQUALVERIFY && + pops[19].opcode.value == OP_CHECKSIG if !isAtomicSwap { return nil, nil } pushes := new(AtomicSwapDataPushes) - copy(pushes.SecretHash[:], pops[2].data) - copy(pushes.RecipientHash160[:], pops[6].data) - copy(pushes.RefundHash160[:], pops[13].data) - if pops[8].data != nil { - locktime, err := makeScriptNum(pops[8].data, true, 5) + copy(pushes.SecretHash[:], pops[5].data) + copy(pushes.RecipientHash160[:], pops[9].data) + copy(pushes.RefundHash160[:], pops[16].data) + if pops[2].data != nil { + locktime, err := makeScriptNum(pops[2].data, true, 5) + if err != nil { + return nil, nil + } + pushes.SecretSize = int64(locktime) + } else if op := pops[2].opcode; isSmallInt(op) { + pushes.SecretSize = int64(asSmallInt(op)) + } else { + return nil, nil + } + if pops[11].data != nil { + locktime, err := makeScriptNum(pops[11].data, true, 5) if err != nil { return nil, nil } pushes.LockTime = int64(locktime) - } else if op := pops[8].opcode; isSmallInt(op) { + } else if op := pops[11].opcode; isSmallInt(op) { pushes.LockTime = int64(asSmallInt(op)) } else { return nil, nil