-
Notifications
You must be signed in to change notification settings - Fork 8
/
dlc.go
86 lines (78 loc) · 2.73 KB
/
dlc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package script
import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
)
// FundScript is a 2-of-2 multisig script
//
// ScriptCode:
// OP_2
// <public key first party>
// <public key second party>
// OP_2
// OP_CHECKMULTISIG
func FundScript(pub1, pub2 *btcec.PublicKey) (script []byte, err error) {
builder := txscript.NewScriptBuilder()
builder.AddOp(txscript.OP_2)
builder.AddData(pub1.SerializeCompressed())
builder.AddData(pub2.SerializeCompressed())
builder.AddOp(txscript.OP_2)
builder.AddOp(txscript.OP_CHECKMULTISIG)
return builder.Script()
}
// WitnessForFundScript constructs a witness for fund script
func WitnessForFundScript(sign1, sign2, sc []byte) wire.TxWitness {
return wire.TxWitness{[]byte{}, sign1, sign2, sc}
}
// ContractExecutionDelay is a delay used in ContractExecutionScript
const ContractExecutionDelay = 144
// ContractExecutionScript returns a contract execution script.
//
// Script Code:
// OP_IF
// <public key a + message public key>
// OP_ELSE
// delay(fix 144)
// OP_CHECKSEQUENCEVERIFY
// OP_DROP
// <public key b>
// OP_ENDIF
// OP_CHECKSIG
//
// The if block can be passed when the contractor A has a valid oracle's sign to the message.
// But if the contractor sends this transaction without the oracle's valid sign,
// the else block will be used by the other party B after the delay time (1 day approximately).
// Please check the original paper for more details.
//
// https://adiabat.github.io/dlc.pdf
func ContractExecutionScript(puba, pubb, pubm *btcec.PublicKey) ([]byte, error) {
// pub key a + message pub key
pubam := &btcec.PublicKey{}
pubam.X, pubam.Y = btcec.S256().Add(puba.X, puba.Y, pubm.X, pubm.Y)
delay := uint16(ContractExecutionDelay)
csvflg := uint32(0x00000000)
builder := txscript.NewScriptBuilder()
builder.AddOp(txscript.OP_IF)
builder.AddData(pubam.SerializeCompressed())
builder.AddOp(txscript.OP_ELSE)
builder.AddInt64(int64(delay) + int64(csvflg))
builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY)
builder.AddOp(txscript.OP_DROP)
builder.AddData(pubb.SerializeCompressed())
builder.AddOp(txscript.OP_ENDIF)
builder.AddOp(txscript.OP_CHECKSIG)
return builder.Script()
}
// WitnessForCEScript constructs a witness that unlocks a contract execution script.
// This function use the OP_IF block
func WitnessForCEScript(
sign []byte, script []byte) wire.TxWitness {
return wire.TxWitness{sign, []byte{1}, script}
}
// WitnessForCEScriptAfterDelay constructs a witness that unlocks a contract execution script.
// This function use the OP_ELSE block that can be valid after the delay
func WitnessForCEScriptAfterDelay(
sign []byte, script []byte) wire.TxWitness {
return wire.TxWitness{sign, []byte{}, script}
}