diff --git a/clmscript/script.go b/clmscript/script.go index 37fd01d..b443a99 100644 --- a/clmscript/script.go +++ b/clmscript/script.go @@ -3,6 +3,7 @@ package clmscript import ( "bytes" "crypto/sha256" + "math/big" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/txscript" @@ -180,6 +181,25 @@ func IncrementKey(key *btcec.PublicKey) *btcec.PublicKey { } } +// DecrementKey is the opposite of IncrementKey, it "subtracts one" from the +// current key to arrive at the key used before the IncrementKey operation. +func DecrementKey(key *btcec.PublicKey) *btcec.PublicKey { + // priorKey = key - G + // priorKey = (key.x, key.y) + (G.x, -G.y) + curveParams := btcec.S256().Params() + negY := new(big.Int).Neg(curveParams.Gy) + negY = negY.Mod(negY, curveParams.P) + x, y := key.Curve.Add( + key.X, key.Y, curveParams.Gx, negY, + ) + + return &btcec.PublicKey{ + X: x, + Y: y, + Curve: btcec.S256(), + } +} + // LocateOutputScript determines whether a transaction includes an output with a // specific script. If it does, the output index is returned. func LocateOutputScript(tx *wire.MsgTx, script []byte) (uint32, bool) { diff --git a/clmscript/script_test.go b/clmscript/script_test.go new file mode 100644 index 0000000..af4a588 --- /dev/null +++ b/clmscript/script_test.go @@ -0,0 +1,37 @@ +package clmscript + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec" + "github.com/stretchr/testify/require" +) + +const ( + numOperations = 1000 +) + +// TestIncrementDecrementKey makes sure that incrementing and decrementing an EC +// public key are inverse operations to each other. +func TestIncrementDecrementKey(t *testing.T) { + t.Parallel() + + privKey, err := btcec.NewPrivateKey(btcec.S256()) + require.NoError(t, err) + + randomStartBatchKey := privKey.PubKey() + + // Increment the key numOperations times. + currentKey := randomStartBatchKey + for i := 0; i < numOperations; i++ { + currentKey = IncrementKey(currentKey) + } + + // Decrement the key again. + for i := 0; i < numOperations; i++ { + currentKey = DecrementKey(currentKey) + } + + // We should arrive at the same start key again. + require.Equal(t, randomStartBatchKey, currentKey) +}