Last active
March 3, 2024 07:11
-
-
Save msinkec/27f8235dd3ad94b64829def5408acec5 to your computer and use it in GitHub Desktop.
TSS Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Deployed contract: 3c0d8b44f8740a0c45162fa6bb6835808b9b04a884853fcb597af1a0812d6345 | |
tx: 010000000145632d81a0f17a59cb3f8584a8049b8b803568bba62f16450c0a74f8448b0d3c0000000000ffffffff0184030000000000001976a91446f320a7e7325a41829e13b016f1dfceee8ab37388ac00000000 | |
sighash preimage: 01000000d544095762018685b1125f75040495deae1a6a78063ca09313aa0f827c6618a43bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e7066504445632d81a0f17a59cb3f8584a8049b8b803568bba62f16450c0a74f8448b0d3c000000001976a914f2a684c7ada5dd4c447ce03f2e50990c0e181f0488ace803000000000000ffffffff4657a850644e1a190c4b06bf681443752eddb949cce4c81751db4c45c61052990000000041000000 | |
sighash f7ab4253b131f70e698051aa621d1ae09665500ef4580d0d2decbc0d4b863671 | |
Sig (r, s): 114836438995585026443311608703469012746226023187493091108812467319065332271518 46571976558762956347626225494771745362039354849912631975526154502213652815393 | |
Sig (hex): 3045022100fde31f027463d4390a9a575f9f5939d602da393c55e8f5b0a31d246d6595c99e022066f6cdfb03abc3b27ab4f88c501f9388ed25602dab53f9d67aadf18343a19e2141 | |
tx (signed): 010000000145632d81a0f17a59cb3f8584a8049b8b803568bba62f16450c0a74f8448b0d3c000000006b483045022100fde31f027463d4390a9a575f9f5939d602da393c55e8f5b0a31d246d6595c99e022066f6cdfb03abc3b27ab4f88c501f9388ed25602dab53f9d67aadf18343a19e21412102a89d4d9bf1e8c8689ff79e3aaa35375c5686829238b31cc605bd2b903a4bae85ffffffff0184030000000000001976a91446f320a7e7325a41829e13b016f1dfceee8ab37388ac00000000 | |
Call: cfc1704361367d902da142c3307c4d0ef9cfe6c6e5d882af258c3a1964ebe9b5 | |
Links: | |
https://test.whatsonchain.com/tx/3c0d8b44f8740a0c45162fa6bb6835808b9b04a884853fcb597af1a0812d6345 | |
https://test.whatsonchain.com/tx/cfc1704361367d902da142c3307c4d0ef9cfe6c6e5d882af258c3a1964ebe9b5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/ecdsa" | |
"crypto/sha256" | |
"encoding/hex" | |
"fmt" | |
"math/big" | |
"runtime" | |
"sync/atomic" | |
"testing" | |
"golang.org/x/crypto/ripemd160" | |
"github.com/ipfs/go-log" | |
"github.com/stretchr/testify/assert" | |
"github.com/bnb-chain/tss-lib/v2/common" | |
"github.com/bnb-chain/tss-lib/v2/ecdsa/keygen" | |
"github.com/bnb-chain/tss-lib/v2/test" | |
"github.com/bnb-chain/tss-lib/v2/tss" | |
) | |
const ( | |
testParticipants = 5 | |
testThreshold = 3 | |
) | |
func setUp(level string) { | |
if err := log.SetLogLevel("tss-lib", level); err != nil { | |
panic(err) | |
} | |
} | |
func main() { | |
setUp("info") | |
threshold := testThreshold | |
// PHASE: load keygen fixtures | |
keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) | |
pubKeyHex := publicKeyToHexCompressed(keys[0].ECDSAPub.ToECDSAPubKey()) | |
addrHex, _ := compressedPubKeyToAddress(pubKeyHex) | |
fmt.Printf("Pub Key (x, y): %s %s\n", keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y()) | |
fmt.Printf("Pub Key (hex, compressed): %s\n", pubKeyHex) | |
fmt.Printf("Address (hex): %s\n", addrHex) | |
// PHASE: signing | |
// use a shuffled selection of the list of parties for this test | |
p2pCtx := tss.NewPeerContext(signPIDs) | |
parties := make([]*LocalParty, 0, len(signPIDs)) | |
errCh := make(chan *tss.Error, len(signPIDs)) | |
outCh := make(chan tss.Message, len(signPIDs)) | |
endCh := make(chan *common.SignatureData, len(signPIDs)) | |
updater := test.SharedPartyUpdater | |
msgData, _ := hex.DecodeString("f7ab4253b131f70e698051aa621d1ae09665500ef4580d0d2decbc0d4b863671") // TODO: Put tx sighash here | |
// init the parties | |
for i := 0; i < len(signPIDs); i++ { | |
params := tss.NewParameters(tss.S256(), p2pCtx, signPIDs[i], len(signPIDs), threshold) | |
P := NewLocalParty(new(big.Int).SetBytes(msgData), params, keys[i], outCh, endCh, len(msgData)).(*LocalParty) | |
parties = append(parties, P) | |
go func(P *LocalParty) { | |
if err := P.Start(); err != nil { | |
errCh <- err | |
} | |
}(P) | |
} | |
var ended int32 | |
signing: | |
for { | |
fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) | |
select { | |
case err := <-errCh: | |
common.Logger.Errorf("Error: %s", err) | |
break signing | |
case msg := <-outCh: | |
dest := msg.GetTo() | |
if dest == nil { | |
for _, P := range parties { | |
if P.PartyID().Index == msg.GetFrom().Index { | |
continue | |
} | |
go updater(P, msg, errCh) | |
} | |
} else { | |
if dest[0].Index == msg.GetFrom().Index { | |
fmt.Printf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) | |
exit(1) | |
} | |
go updater(parties[dest[0].Index], msg, errCh) | |
} | |
case <-endCh: | |
atomic.AddInt32(&ended, 1) | |
if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { | |
fmt.Printf("Done. Received signature data from %d participants", ended) | |
R := parties[0].temp.bigR | |
//r := parties[0].temp.rx | |
modN := common.ModInt(tss.S256().Params().N) | |
// BEGIN check s correctness | |
sumS := big.NewInt(0) | |
for _, p := range parties { | |
sumS = modN.Add(sumS, p.temp.si) | |
} | |
// END check s correctness | |
fmt.Printf("Sig (r, s): %s %s\n", R.X(), sumS) | |
// BEGIN ECDSA verify | |
pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() | |
pk := ecdsa.PublicKey{ | |
Curve: tss.EC(), | |
X: pkX, | |
Y: pkY, | |
} | |
ok := ecdsa.Verify(&pk, msgData, R.X(), sumS) | |
fmt.Println(ok) | |
// END ECDSA verify | |
break signing | |
} | |
} | |
} | |
} | |
func fillBytes(x *big.Int, buf []byte) []byte { | |
b := x.Bytes() | |
if len(b) > len(buf) { | |
panic("buffer too small") | |
} | |
offset := len(buf) - len(b) | |
for i := range buf { | |
if i < offset { | |
buf[i] = 0 | |
} else { | |
buf[i] = b[i-offset] | |
} | |
} | |
return buf | |
} | |
// Serializes a public key into compressed form (0x02/0x03 + x) | |
func publicKeyToHexCompressed(pubKey *ecdsa.PublicKey) string { | |
xBytes := pubKey.X.Bytes() | |
// Ensure the bytes are 32 bytes long | |
paddedX := append(make([]byte, 32-len(xBytes)), xBytes...) | |
var compressed []byte | |
if pubKey.Y.Bit(0) == 0 { // Even Y | |
compressed = append([]byte{0x02}, paddedX...) | |
} else { // Odd Y | |
compressed = append([]byte{0x03}, paddedX...) | |
} | |
return hex.EncodeToString(compressed) | |
} | |
// Converts a hex-encoded compressed public key to a Bitcoin address | |
func compressedPubKeyToAddress(compressedPubKeyHex string) (string, error) { | |
// Decode the hex-encoded compressed public key | |
pubKeyBytes, err := hex.DecodeString(compressedPubKeyHex) | |
if err != nil { | |
return "", err | |
} | |
// SHA-256 hashing | |
shaHash := sha256.New() | |
shaHash.Write(pubKeyBytes) | |
shaResult := shaHash.Sum(nil) | |
// RIPEMD-160 hashing | |
r160Hash := ripemd160.New() | |
r160Hash.Write(shaResult) | |
ripemdResult := r160Hash.Sum(nil) | |
return hex.EncodeToString(ripemdResult), nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment