[FEATURE] - cardano multisig wallet with staking
ekko-Huang opened this issue · 0 comments
ekko-Huang commented
hey guys.
I want to send a registration transaction for a multi-signature wallet, but I don't know how to organize NativeScript and signatures.
import (
"encoding/hex"
"fmt"
"log"
"testing"
"github.com/btcsuite/btcutil/bech32"
"github.com/echovl/cardano-go"
"github.com/echovl/cardano-go/crypto"
"github.com/fivebinaries/go-cardano-serialization/address"
"github.com/fivebinaries/go-cardano-serialization/bip32"
"github.com/fivebinaries/go-cardano-serialization/network"
"github.com/tyler-smith/go-bip39"
)
func TestMultiSignDelegationTx(t *testing.T) {
//m1 := "canyon soft bitter into mixed find cover method junk glide place rabbit"
m1 := "where visa pizza bronze tumble indicate loud endorse slice secret hip fix"
m2 := "stem mandate sand lecture hip ancient issue happy office about miracle bounce"
m3 := "shallow remember arrest magnet resist aspect equip trash season sell bless clown"
p1 := getPaymentPrvKey(getRootKey(m1))
payment1 := p1.Public()
payment1Hash := payment1.PublicKey().Hash()
s1 := getStakePrvKey(getRootKey(m1))
stake1 := s1.Public()
stake1Hash := stake1.PublicKey().Hash()
p2 := getPaymentPrvKey(getRootKey(m2))
payment2 := p2.Public()
payment2Hash := payment2.PublicKey().Hash()
s2 := getStakePrvKey(getRootKey(m2))
stake2 := s2.Public()
stake2Hash := stake2.PublicKey().Hash()
p3 := getPaymentPrvKey(getRootKey(m3))
payment3 := p3.Public()
payment3Hash := payment3.PublicKey().Hash()
s3 := getStakePrvKey(getRootKey(m3))
stake3 := s3.Public()
stake3Hash := stake3.PublicKey().Hash()
n := cardano.NativeScript{
Type: ScriptAtLeast, // Require-Of-M
N: 2,
Scripts: []cardano.NativeScript{
{
Type: ScriptPubKey,
KeyHash: payment1Hash[:],
},
{
Type: ScriptPubKey,
KeyHash: payment2Hash[:],
},
{
Type: ScriptPubKey,
KeyHash: payment3Hash[:],
},
},
}
paymentScriptHash, err := n.Hash()
if err != nil {
panic(err)
}
s := cardano.NativeScript{
Type: ScriptAtLeast, // Require-Of-M
N: 2,
Scripts: []cardano.NativeScript{
{
Type: ScriptPubKey,
KeyHash: stake1Hash[:],
},
{
Type: ScriptPubKey,
KeyHash: stake2Hash[:],
},
{
Type: ScriptPubKey,
KeyHash: stake3Hash[:],
},
},
}
stakeScriptHash, err := s.Hash()
if err != nil {
panic(err)
}
multisign := address.NewBaseAddress(
network.TestNet(),
&address.StakeCredential{
Kind: address.ScriptStakeCredentialType,
Payload: paymentScriptHash,
},
&address.StakeCredential{
Kind: address.ScriptStakeCredentialType,
Payload: stakeScriptHash,
},
)
fmt.Println("multiSign Address:", multisign.String())
fmt.Println("stake Address:", multisign.ToReward().String())
fmt.Println("stakeHash", hex.EncodeToString(stakeScriptHash))
txBuilder := cardano.NewTxBuilder(alonzoProtocol)
stakeByte, _ := s.Bytes()
stakeByte = append([]byte{byte(0)}, stakeByte...)
// create RegistrationCert
stakeDelCert, err := cardano.NewStakeRegistrationCertificate(stakeByte)
if err != nil {
panic(err)
}
rAddr, _ := cardano.NewAddress(multisign.String())
txInputHash, _ := cardano.NewHash32("e55ae4a146ff4779fc88b772102fae92205b637db41394d53b16d33b658c2c44")
txInputAmount := cardano.NewValue(20000000)
txBuilder.AddInputs(cardano.NewTxInput(txInputHash, 0, txInputAmount))
txBuilder.AddOutputs(cardano.NewTxOutput(rAddr, cardano.NewValue(17811223)))
txBuilder.SetFee(188777) //
txBuilder.AddCertificate(stakeDelCert)
txBuilder.AddNativeScript(n)
txBuilder.AddNativeScript(s)
txBuilder.Sign(
crypto.PrvKey(p1),
crypto.PrvKey(p2),
crypto.PrvKey(s1),
crypto.PrvKey(s2),
)
fmt.Println(hex.EncodeToString(p1.Public().PublicKey()), hex.EncodeToString(p2.Public().PublicKey()))
tx, err := txBuilder.Build()
if err != nil {
panic(err)
}
fmt.Println(fmt.Sprintf("%+v", tx))
txHash, err := SubmitTx(tx)
if err != nil {
panic(err)
}
fmt.Println(txHash)
}
func getRootKey(mnemonic string) bip32.XPrv {
entropy, err := bip39.EntropyFromMnemonic(mnemonic)
if err != nil {
panic(err)
}
rootKey := bip32.FromBip39Entropy(
entropy,
[]byte{},
)
return rootKey
}
func getPaymentPrvKey(rootKey bip32.XPrv) bip32.XPrv {
accountKey := rootKey.Derive(harden(1852)).Derive(harden(1815)).Derive(harden(0))
paymentKey := accountKey.Derive(0).Derive(0)
return paymentKey
}
func getStakePrvKey(rootKey bip32.XPrv) bip32.XPrv {
accountKey := rootKey.Derive(harden(1852)).Derive(harden(1815)).Derive(harden(0))
stakeKey := accountKey.Derive(2).Derive(0)
return stakeKey
}
errorMsg :
map[error:Bad Request message:{"contents":{"contents":{"contents":{"era":"ShelleyBasedEraBabbage","error":[{"contents":{"contents":{"contents":{"contents":["74725e00e926bd68e1e787e5f1f57b35c059d95002f8ad33d420050e"],"tag":"ExtraneousScriptWitnessesUTXOW"},"tag":"ShelleyInAlonzoUtxowPredFailure"},"tag":"AlonzoInBabbageUtxowPredFailure"},"tag":"UtxowFailure"}],"kind":"ShelleyTxValidationError"},"tag":"TxValidationErrorInCardanoMode"},"tag":"TxCmdTxSubmitValidationError"},"tag":"TxSubmitFail"} status_code:400]