Skip to content

Instantly share code, notes, and snippets.

@cgcardona
Created August 3, 2022 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgcardona/7f8e8a87f1ab2adfcae800cb7cd168f1 to your computer and use it in GitHub Desktop.
Save cgcardona/7f8e8a87f1ab2adfcae800cb7cd168f1 to your computer and use it in GitHub Desktop.
Import AVAX to the X-Chain from the C-Chain
package main
import (
"encoding/hex"
"errors"
"fmt"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/cb58"
"github.com/ava-labs/avalanchego/utils/crypto"
"github.com/ava-labs/avalanchego/utils/formatting"
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/ava-labs/avalanchego/vms/avm/fxs"
"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
)
func main() {
var pkHex, parseErr = hex.DecodeString("56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027")
if parseErr != nil {
panic(parseErr)
}
var privateKey = secp256k1.PrivKeyFromBytes(pkHex)
var cb58str, cb58Err = cb58.Encode(privateKey.Serialize())
if cb58Err != nil {
panic(cb58Err)
}
fmt.Println(cb58str)
var fujiXChainIDStr = "qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7"
var fujiXChainIDBytes, err = cb58.Decode(fujiXChainIDStr)
if err != nil {
panic(err)
}
var fujiXChainID, hashErr = hashing.ToHash256(fujiXChainIDBytes)
if hashErr != nil {
panic(hashErr)
}
var fujiCChainIDStr = "BR28ypgLATNS6PbtHMiJ7NQ61vfpT27Hj8tAcZ1AHsfU5cz88"
var fujiCChainIDBytes, decodeCB58Err = cb58.Decode(fujiCChainIDStr)
if decodeCB58Err != nil {
panic(decodeCB58Err)
}
var fujiCChainID, hashCChainErr = hashing.ToHash256(fujiCChainIDBytes)
if hashCChainErr != nil {
panic(hashCChainErr)
}
var utxoBytes, decodeError = formatting.Decode(formatting.Hex, "0x00000b79b503074f910eafc664fd5d88a9671d4afd157422907d9bde9e419daf6cdc0000000017cc8b1578ba383544d163958822d8abd3849bb9dfabe39fcbc3e7ee8811fe2f000000070000000000989680000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c9b6025ca")
if decodeError != nil {
panic(decodeError)
}
var utxo avax.UTXO
var parser, newParserErr = txs.NewParser([]fxs.Fx{
&secp256k1fx.Fx{},
})
if newParserErr != nil {
panic(newParserErr)
}
var codec = parser.Codec()
var _, unmarshalErr = codec.Unmarshal(utxoBytes, &utxo)
if unmarshalErr != nil {
panic(unmarshalErr)
}
var baseTx = txs.BaseTx{
BaseTx: avax.BaseTx{
NetworkID: 1337,
BlockchainID: fujiXChainID,
Outs: make([]*avax.TransferableOutput, 1),
},
}
var shortID, convertErr = ids.ToShortID(hashing.PubkeyBytesToAddress(privateKey.PubKey().SerializeCompressed()))
if convertErr != nil {
panic(convertErr)
}
baseTx.BaseTx.Outs[0] = &avax.TransferableOutput{
Asset: avax.Asset{ID: utxo.AssetID()},
Out: &secp256k1fx.TransferOutput{
Amt: 1e7 - 1e6,
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{shortID},
},
},
}
var utx = txs.ImportTx{
BaseTx: baseTx,
SourceChain: fujiCChainID,
ImportedIns: []*avax.TransferableInput{
{
UTXOID: avax.UTXOID{
TxID: utxo.TxID,
OutputIndex: utxo.OutputIndex,
},
Asset: avax.Asset{
ID: utxo.AssetID(),
},
In: &secp256k1fx.TransferInput{
Amt: 1e7,
Input: secp256k1fx.Input{
SigIndices: []uint32{0},
},
},
},
},
}
var tx = txs.Tx{Unsigned: &utx}
var rawTx, marshalErr = codec.Marshal(txs.CodecVersion, &utx)
if marshalErr != nil {
panic(marshalErr)
}
var hashRawTx = hashing.ComputeHash256(rawTx)
//sign
var rawSig = ecdsa.SignCompact(privateKey, hashRawTx, false)
var sig, signErr = rawSigToSig(rawSig)
if signErr != nil {
panic(signErr)
}
// build signed tx
var sign [crypto.SECP256K1RSigLen]byte
copy(sign[:], sig)
var signs = [][crypto.SECP256K1RSigLen]byte{sign}
tx.Creds = []*fxs.FxCredential{
{
Verifiable: &secp256k1fx.Credential{
Sigs: signs,
},
},
}
var signedBytes, marshalSignedErr = codec.Marshal(txs.CodecVersion, &tx)
if marshalSignedErr != nil {
panic(marshalSignedErr)
}
tx.Initialize(rawTx, signedBytes)
var txHex, hexErr = formatting.Encode(formatting.Hex, tx.Bytes())
if hexErr != nil {
panic(hexErr)
}
fmt.Println("raw tx hex", txHex)
}
func rawSigToSig(sig []byte) ([]byte, error) {
if len(sig) != crypto.SECP256K1RSigLen {
return nil, errors.New("invalid signature length")
}
recCode := sig[0]
copy(sig, sig[1:])
sig[crypto.SECP256K1RSigLen-1] = recCode - 27
return sig, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment