Created
August 3, 2022 21:55
-
-
Save cgcardona/7f8e8a87f1ab2adfcae800cb7cd168f1 to your computer and use it in GitHub Desktop.
Import AVAX to the X-Chain from the C-Chain
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 ( | |
"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