mirror of https://github.com/poanetwork/gecko.git
Finished first pass of APIs
This commit is contained in:
parent
9da52e70c0
commit
65393729d2
|
@ -54,12 +54,9 @@ func (t *txJob) Execute() {
|
|||
case choices.Unknown, choices.Rejected:
|
||||
t.numDropped.Inc()
|
||||
case choices.Processing:
|
||||
if err := t.tx.Verify(); err == nil {
|
||||
t.tx.Accept()
|
||||
t.numAccepted.Inc()
|
||||
} else {
|
||||
t.numDropped.Inc()
|
||||
}
|
||||
t.tx.Verify()
|
||||
t.tx.Accept()
|
||||
t.numAccepted.Inc()
|
||||
}
|
||||
}
|
||||
func (t *txJob) Bytes() []byte { return t.tx.Bytes() }
|
||||
|
|
|
@ -51,12 +51,9 @@ func (b *blockJob) Execute() {
|
|||
case choices.Unknown, choices.Rejected:
|
||||
b.numDropped.Inc()
|
||||
case choices.Processing:
|
||||
if err := b.blk.Verify(); err == nil {
|
||||
b.blk.Accept()
|
||||
b.numAccepted.Inc()
|
||||
} else {
|
||||
b.numDropped.Inc()
|
||||
}
|
||||
b.blk.Verify()
|
||||
b.blk.Accept()
|
||||
b.numAccepted.Inc()
|
||||
}
|
||||
}
|
||||
func (b *blockJob) Bytes() []byte { return b.blk.Bytes() }
|
||||
|
|
|
@ -37,20 +37,6 @@ type BaseTx struct {
|
|||
Ins []*ava.TransferableInput `serialize:"true"` // The inputs to this transaction
|
||||
}
|
||||
|
||||
// NetworkID is the ID of the network on which this transaction exists
|
||||
func (t *BaseTx) NetworkID() uint32 { return t.NetID }
|
||||
|
||||
// ChainID is the ID of the chain on which this transaction exists
|
||||
func (t *BaseTx) ChainID() ids.ID { return t.BCID }
|
||||
|
||||
// Outputs track which outputs this transaction is producing. The returned array
|
||||
// should not be modified.
|
||||
func (t *BaseTx) Outputs() []*ava.TransferableOutput { return t.Outs }
|
||||
|
||||
// Inputs track which UTXOs this transaction is consuming. The returned array
|
||||
// should not be modified.
|
||||
func (t *BaseTx) Inputs() []*ava.TransferableInput { return t.Ins }
|
||||
|
||||
// InputUTXOs track which UTXOs this transaction is consuming.
|
||||
func (t *BaseTx) InputUTXOs() []*ava.UTXOID {
|
||||
utxos := []*ava.UTXOID(nil)
|
||||
|
|
|
@ -167,19 +167,7 @@ func TestBaseTxGetters(t *testing.T) {
|
|||
|
||||
txID := tx.ID()
|
||||
|
||||
if netID := tx.NetworkID(); netID != networkID {
|
||||
t.Fatalf("Wrong network ID returned")
|
||||
} else if bcID := tx.ChainID(); !bcID.Equals(chainID) {
|
||||
t.Fatalf("Wrong chain ID returned")
|
||||
} else if outs := tx.Outputs(); len(outs) != 1 {
|
||||
t.Fatalf("Outputs returned wrong number of outs")
|
||||
} else if out := outs[0]; out != tx.Outs[0] {
|
||||
t.Fatalf("Outputs returned wrong output")
|
||||
} else if ins := tx.Inputs(); len(ins) != 1 {
|
||||
t.Fatalf("Inputs returned wrong number of ins")
|
||||
} else if in := ins[0]; in != tx.Ins[0] {
|
||||
t.Fatalf("Inputs returned wrong input")
|
||||
} else if assets := tx.AssetIDs(); assets.Len() != 1 {
|
||||
if assets := tx.AssetIDs(); assets.Len() != 1 {
|
||||
t.Fatalf("Wrong number of assets returned")
|
||||
} else if !assets.Contains(asset) {
|
||||
t.Fatalf("Wrong asset returned")
|
||||
|
@ -191,8 +179,6 @@ func TestBaseTxGetters(t *testing.T) {
|
|||
t.Fatalf("Wrong output index returned")
|
||||
} else if assetID := utxo.AssetID(); !assetID.Equals(asset) {
|
||||
t.Fatalf("Wrong asset ID returned")
|
||||
} else if utxoOut := utxo.Out; utxoOut != out.Out {
|
||||
t.Fatalf("Wrong output returned")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
type ExportTx struct {
|
||||
BaseTx `serialize:"true"`
|
||||
|
||||
ExportOuts []*ava.TransferableOutput `serialize:"true"` // The outputs this transaction is sending to the other chain
|
||||
Outs []*ava.TransferableOutput `serialize:"true"` // The outputs this transaction is sending to the other chain
|
||||
}
|
||||
|
||||
// SyntacticVerify that this transaction is well-formed.
|
||||
|
@ -32,6 +32,16 @@ func (t *ExportTx) SyntacticVerify(ctx *snow.Context, c codec.Codec, _ int) erro
|
|||
}
|
||||
|
||||
fc := ava.NewFlowChecker()
|
||||
for _, out := range t.BaseTx.Outs {
|
||||
if err := out.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
fc.Produce(out.AssetID(), out.Output().Amount())
|
||||
}
|
||||
if !ava.IsSortedTransferableOutputs(t.BaseTx.Outs, c) {
|
||||
return errOutputsNotSorted
|
||||
}
|
||||
|
||||
for _, out := range t.Outs {
|
||||
if err := out.Verify(); err != nil {
|
||||
return err
|
||||
|
@ -42,16 +52,6 @@ func (t *ExportTx) SyntacticVerify(ctx *snow.Context, c codec.Codec, _ int) erro
|
|||
return errOutputsNotSorted
|
||||
}
|
||||
|
||||
for _, out := range t.ExportOuts {
|
||||
if err := out.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
fc.Produce(out.AssetID(), out.Output().Amount())
|
||||
}
|
||||
if !ava.IsSortedTransferableOutputs(t.ExportOuts, c) {
|
||||
return errOutputsNotSorted
|
||||
}
|
||||
|
||||
for _, in := range t.Ins {
|
||||
if err := in.Verify(); err != nil {
|
||||
return err
|
||||
|
@ -102,7 +102,7 @@ func (t *ExportTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verifiab
|
|||
}
|
||||
}
|
||||
|
||||
for _, out := range t.ExportOuts {
|
||||
for _, out := range t.Outs {
|
||||
if !out.AssetID().Equals(vm.ava) {
|
||||
return errWrongAssetID
|
||||
}
|
||||
|
@ -121,11 +121,11 @@ func (t *ExportTx) ExecuteWithSideEffects(vm *VM, batch database.Batch) error {
|
|||
vsmDB := versiondb.New(smDB)
|
||||
|
||||
state := ava.NewPrefixedState(vsmDB, vm.codec)
|
||||
for i, out := range t.ExportOuts {
|
||||
for i, out := range t.Outs {
|
||||
utxo := &ava.UTXO{
|
||||
UTXOID: ava.UTXOID{
|
||||
TxID: txID,
|
||||
OutputIndex: uint32(len(t.Outs) + i),
|
||||
OutputIndex: uint32(len(t.BaseTx.Outs) + i),
|
||||
},
|
||||
Asset: ava.Asset{ID: out.AssetID()},
|
||||
Out: out.Out,
|
||||
|
|
|
@ -168,7 +168,7 @@ func TestIssueExportTx(t *testing.T) {
|
|||
},
|
||||
}},
|
||||
},
|
||||
ExportOuts: []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Outs: []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Asset: ava.Asset{ID: avaID},
|
||||
Out: &secp256k1fx.TransferOutput{
|
||||
Amt: 50000,
|
||||
|
@ -301,7 +301,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) {
|
|||
},
|
||||
}},
|
||||
},
|
||||
ExportOuts: []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Outs: []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Asset: ava.Asset{ID: avaID},
|
||||
Out: &secp256k1fx.TransferOutput{
|
||||
Amt: 50000,
|
||||
|
|
|
@ -20,8 +20,7 @@ import (
|
|||
type ImportTx struct {
|
||||
BaseTx `serialize:"true"`
|
||||
|
||||
Outs []*ava.TransferableOutput `serialize:"true"` // The outputs of this transaction
|
||||
Ins []*ava.TransferableInput `serialize:"true"` // The inputs to this transaction
|
||||
Ins []*ava.TransferableInput `serialize:"true"` // The inputs to this transaction
|
||||
}
|
||||
|
||||
// InputUTXOs track which UTXOs this transaction is consuming.
|
||||
|
@ -43,25 +42,6 @@ func (t *ImportTx) AssetIDs() ids.Set {
|
|||
return assets
|
||||
}
|
||||
|
||||
// UTXOs returns the UTXOs transaction is producing.
|
||||
func (t *ImportTx) UTXOs() []*ava.UTXO {
|
||||
txID := t.ID()
|
||||
utxos := t.BaseTx.UTXOs()
|
||||
|
||||
for _, out := range t.Outs {
|
||||
utxos = append(utxos, &ava.UTXO{
|
||||
UTXOID: ava.UTXOID{
|
||||
TxID: txID,
|
||||
OutputIndex: uint32(len(utxos)),
|
||||
},
|
||||
Asset: ava.Asset{ID: out.AssetID()},
|
||||
Out: out.Out,
|
||||
})
|
||||
}
|
||||
|
||||
return utxos
|
||||
}
|
||||
|
||||
var (
|
||||
errNoImportInputs = errors.New("no import inputs")
|
||||
)
|
||||
|
@ -71,14 +51,14 @@ func (t *ImportTx) SyntacticVerify(ctx *snow.Context, c codec.Codec, numFxs int)
|
|||
switch {
|
||||
case t == nil:
|
||||
return errNilTx
|
||||
case t.NetID != ctx.NetworkID:
|
||||
return errWrongNetworkID
|
||||
case !t.BCID.Equals(ctx.ChainID):
|
||||
return errWrongChainID
|
||||
case len(t.Ins) == 0:
|
||||
return errNoImportInputs
|
||||
}
|
||||
|
||||
if err := t.BaseTx.SyntacticVerify(ctx, c, numFxs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fc := ava.NewFlowChecker()
|
||||
for _, out := range t.Outs {
|
||||
if err := out.Verify(); err != nil {
|
||||
|
@ -90,6 +70,16 @@ func (t *ImportTx) SyntacticVerify(ctx *snow.Context, c codec.Codec, numFxs int)
|
|||
return errOutputsNotSorted
|
||||
}
|
||||
|
||||
for _, in := range t.BaseTx.Ins {
|
||||
if err := in.Verify(); err != nil {
|
||||
return err
|
||||
}
|
||||
fc.Consume(in.AssetID(), in.Input().Amount())
|
||||
}
|
||||
if !ava.IsSortedAndUniqueTransferableInputs(t.BaseTx.Ins) {
|
||||
return errInputsNotSortedUnique
|
||||
}
|
||||
|
||||
for _, in := range t.Ins {
|
||||
if err := in.Verify(); err != nil {
|
||||
return err
|
||||
|
|
|
@ -34,8 +34,6 @@ func TestImportTxSerialization(t *testing.T) {
|
|||
0x00, 0x00, 0x00, 0x00,
|
||||
// number of base inputs:
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// number of outs:
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// number of inputs:
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
// utxoID:
|
||||
|
|
|
@ -948,6 +948,147 @@ func (service *Service) SignMintTx(r *http.Request, args *SignMintTxArgs, reply
|
|||
return nil
|
||||
}
|
||||
|
||||
// SendImportArgs are arguments for passing into SendImport requests
|
||||
type SendImportArgs struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
To string `json:"to"`
|
||||
}
|
||||
|
||||
// SendImportReply defines the SendImport replies returned from the API
|
||||
type SendImportReply struct {
|
||||
TxID ids.ID `json:"txID"`
|
||||
}
|
||||
|
||||
// SendImport returns the ID of the newly created atomic transaction
|
||||
func (service *Service) SendImport(_ *http.Request, args *SendImportArgs, reply *SendImportReply) error {
|
||||
service.vm.ctx.Log.Verbo("SendExport called with username: %s", args.Username)
|
||||
|
||||
toBytes, err := service.vm.Parse(args.To)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem parsing to address: %w", err)
|
||||
}
|
||||
to, err := ids.ToShortID(toBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem parsing to address: %w", err)
|
||||
}
|
||||
|
||||
db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem retrieving user: %w", err)
|
||||
}
|
||||
|
||||
user := userState{vm: service.vm}
|
||||
|
||||
addresses, _ := user.Addresses(db)
|
||||
|
||||
addrs := ids.Set{}
|
||||
addrs.Add(addresses...)
|
||||
utxos, err := service.vm.GetAtomicUTXOs(addrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem retrieving user's atomic UTXOs: %w", err)
|
||||
}
|
||||
|
||||
kc := secp256k1fx.NewKeychain()
|
||||
for _, addr := range addresses {
|
||||
sk, err := user.Key(db, addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem retrieving private key: %w", err)
|
||||
}
|
||||
kc.Add(sk)
|
||||
}
|
||||
|
||||
amount := uint64(0)
|
||||
time := service.vm.clock.Unix()
|
||||
|
||||
ins := []*ava.TransferableInput{}
|
||||
keys := [][]*crypto.PrivateKeySECP256K1R{}
|
||||
for _, utxo := range utxos {
|
||||
if !utxo.AssetID().Equals(service.vm.ava) {
|
||||
continue
|
||||
}
|
||||
inputIntf, signers, err := kc.Spend(utxo.Out, time)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
input, ok := inputIntf.(ava.Transferable)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
spent, err := math.Add64(amount, input.Amount())
|
||||
if err != nil {
|
||||
return errSpendOverflow
|
||||
}
|
||||
amount = spent
|
||||
|
||||
in := &ava.TransferableInput{
|
||||
UTXOID: utxo.UTXOID,
|
||||
Asset: ava.Asset{ID: service.vm.ava},
|
||||
In: input,
|
||||
}
|
||||
|
||||
ins = append(ins, in)
|
||||
keys = append(keys, signers)
|
||||
}
|
||||
|
||||
ava.SortTransferableInputsWithSigners(ins, keys)
|
||||
|
||||
outs := []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Asset: ava.Asset{ID: service.vm.ava},
|
||||
Out: &secp256k1fx.TransferOutput{
|
||||
Amt: amount,
|
||||
Locktime: 0,
|
||||
OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{to},
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
tx := Tx{UnsignedTx: &ImportTx{
|
||||
BaseTx: BaseTx{
|
||||
NetID: service.vm.ctx.NetworkID,
|
||||
BCID: service.vm.ctx.ChainID,
|
||||
Outs: outs,
|
||||
},
|
||||
Ins: ins,
|
||||
}}
|
||||
|
||||
unsignedBytes, err := service.vm.codec.Marshal(&tx.UnsignedTx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem creating transaction: %w", err)
|
||||
}
|
||||
hash := hashing.ComputeHash256(unsignedBytes)
|
||||
|
||||
for _, credKeys := range keys {
|
||||
cred := &secp256k1fx.Credential{}
|
||||
for _, key := range credKeys {
|
||||
sig, err := key.SignHash(hash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem creating transaction: %w", err)
|
||||
}
|
||||
fixedSig := [crypto.SECP256K1RSigLen]byte{}
|
||||
copy(fixedSig[:], sig)
|
||||
|
||||
cred.Sigs = append(cred.Sigs, fixedSig)
|
||||
}
|
||||
tx.Creds = append(tx.Creds, cred)
|
||||
}
|
||||
|
||||
b, err := service.vm.codec.Marshal(tx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem creating transaction: %w", err)
|
||||
}
|
||||
|
||||
txID, err := service.vm.IssueTx(b, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem issuing transaction: %w", err)
|
||||
}
|
||||
|
||||
reply.TxID = txID
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendExportArgs are arguments for passing into SendExport requests
|
||||
type SendExportArgs struct {
|
||||
Username string `json:"username"`
|
||||
|
@ -1083,7 +1224,7 @@ func (service *Service) SendExport(_ *http.Request, args *SendExportArgs, reply
|
|||
Outs: outs,
|
||||
Ins: ins,
|
||||
},
|
||||
ExportOuts: exportOuts,
|
||||
Outs: exportOuts,
|
||||
}}
|
||||
|
||||
unsignedBytes, err := service.vm.codec.Marshal(&tx.UnsignedTx)
|
||||
|
|
|
@ -24,11 +24,6 @@ type UnsignedTx interface {
|
|||
ID() ids.ID
|
||||
Bytes() []byte
|
||||
|
||||
NetworkID() uint32
|
||||
ChainID() ids.ID
|
||||
Outputs() []*ava.TransferableOutput
|
||||
Inputs() []*ava.TransferableInput
|
||||
|
||||
AssetIDs() ids.Set
|
||||
InputUTXOs() []*ava.UTXOID
|
||||
UTXOs() []*ava.UTXO
|
||||
|
|
|
@ -275,6 +275,31 @@ func (vm *VM) IssueTx(b []byte, onDecide func(choices.Status)) (ids.ID, error) {
|
|||
return tx.ID(), nil
|
||||
}
|
||||
|
||||
// GetAtomicUTXOs returns the utxos that at least one of the provided addresses is
|
||||
// referenced in.
|
||||
func (vm *VM) GetAtomicUTXOs(addrs ids.Set) ([]*ava.UTXO, error) {
|
||||
smDB := vm.ctx.SharedMemory.GetDatabase(vm.platform)
|
||||
defer vm.ctx.SharedMemory.ReleaseDatabase(vm.platform)
|
||||
|
||||
state := ava.NewPrefixedState(smDB, vm.codec)
|
||||
|
||||
utxoIDs := ids.Set{}
|
||||
for _, addr := range addrs.List() {
|
||||
utxos, _ := state.PlatformFunds(addr)
|
||||
utxoIDs.Add(utxos...)
|
||||
}
|
||||
|
||||
utxos := []*ava.UTXO{}
|
||||
for _, utxoID := range utxoIDs.List() {
|
||||
utxo, err := state.PlatformUTXO(utxoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
utxos = append(utxos, utxo)
|
||||
}
|
||||
return utxos, nil
|
||||
}
|
||||
|
||||
// GetUTXOs returns the utxos that at least one of the provided addresses is
|
||||
// referenced in.
|
||||
func (vm *VM) GetUTXOs(addrs ids.Set) ([]*ava.UTXO, error) {
|
||||
|
|
|
@ -162,7 +162,7 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
}
|
||||
var subnet *CreateSubnetTx
|
||||
for _, sn := range subnets {
|
||||
if sn.ID.Equals(tx.SubnetID()) {
|
||||
if sn.id.Equals(tx.SubnetID()) {
|
||||
subnet = sn
|
||||
break
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -48,7 +48,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID+1,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -67,7 +67,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -87,7 +87,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -107,7 +107,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -126,7 +126,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix())-1,
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -147,7 +147,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateStartTime.Add(MinimumStakingDuration).Unix())-1,
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -167,7 +167,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateStartTime.Add(MaximumStakingDuration).Unix())+1,
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -187,7 +187,7 @@ func TestAddNonDefaultSubnetValidatorTxSyntacticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -212,7 +212,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix())+1,
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -235,7 +235,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -245,7 +245,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
}
|
||||
_, _, _, _, err = tx.SemanticVerify(vm.DB)
|
||||
if err != nil {
|
||||
t.Log(testSubnet1.ID)
|
||||
t.Log(testSubnet1.id)
|
||||
subnets, err := vm.getSubnets(vm.DB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -253,7 +253,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
if len(subnets) == 0 {
|
||||
t.Fatal("no subnets found")
|
||||
}
|
||||
t.Logf("subnets[0].ID: %v", subnets[0].ID)
|
||||
t.Logf("subnets[0].ID: %v", subnets[0].id)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(DSStartTime.Unix()), // start validating non-default subnet before default subnet
|
||||
uint64(DSEndTime.Unix()),
|
||||
pendingDSValidatorID,
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -324,7 +324,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(DSStartTime.Unix())-1, // start validating non-default subnet before default subnet
|
||||
uint64(DSEndTime.Unix()),
|
||||
pendingDSValidatorID,
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -346,7 +346,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(DSStartTime.Unix()),
|
||||
uint64(DSEndTime.Unix())+1, // stop validating non-default subnet after stopping validating default subnet
|
||||
pendingDSValidatorID,
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -368,7 +368,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(DSStartTime.Unix()), // same start time as for default subnet
|
||||
uint64(DSEndTime.Unix()), // same end time as for default subnet
|
||||
pendingDSValidatorID,
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
@ -389,12 +389,12 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
}
|
||||
|
||||
tx, err = vm.newAddNonDefaultSubnetValidatorTx(
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(newTimestamp.Unix()), // start time
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(newTimestamp.Unix()), // start time
|
||||
uint64(newTimestamp.Add(MinimumStakingDuration).Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -429,7 +429,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()), // start time
|
||||
uint64(defaultValidateEndTime.Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
newAcctKey.(*crypto.PrivateKeySECP256K1R), // tx fee payer
|
||||
|
@ -451,7 +451,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()), // start time
|
||||
uint64(defaultValidateEndTime.Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -465,7 +465,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
SortByStartTime: false,
|
||||
Txs: []TimedTx{tx},
|
||||
},
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
)
|
||||
// Node with ID nodeIDKey.PublicKey().Address() now validating subnet with ID testSubnet1.ID
|
||||
|
||||
|
@ -475,7 +475,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()), // start time
|
||||
uint64(defaultValidateEndTime.Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -494,17 +494,17 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
&EventHeap{
|
||||
SortByStartTime: false,
|
||||
},
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
)
|
||||
|
||||
// Case 9: Too many signatures
|
||||
tx, err = vm.newAddNonDefaultSubnetValidatorTx(
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
uint64(defaultGenesisTime.Add(MinimumStakingDuration).Unix())+1, // end time
|
||||
keys[0].PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1], testSubnet1ControlKeys[2]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -520,12 +520,12 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
|
||||
// Case 10: Too few signatures
|
||||
tx, err = vm.newAddNonDefaultSubnetValidatorTx(
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
uint64(defaultGenesisTime.Add(MinimumStakingDuration).Unix()), // end time
|
||||
keys[0].PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[2]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -541,12 +541,12 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
|
||||
// Case 10: Control Signature from invalid key
|
||||
tx, err = vm.newAddNonDefaultSubnetValidatorTx(
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix()), // start time
|
||||
uint64(defaultGenesisTime.Add(MinimumStakingDuration).Unix()), // end time
|
||||
keys[0].PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], keys[3]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -563,12 +563,12 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
// Case 11: Proposed validator in pending validator set for subnet
|
||||
// First, add validator to pending validator set of subnet
|
||||
tx, err = vm.newAddNonDefaultSubnetValidatorTx(
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix())+1, // start time
|
||||
defaultNonce+1, // nonce
|
||||
defaultWeight, // weight
|
||||
uint64(defaultGenesisTime.Unix())+1, // start time
|
||||
uint64(defaultGenesisTime.Add(MinimumStakingDuration).Unix())+1, // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
testSubnet1.ID, // subnet ID
|
||||
testSubnet1.id, // subnet ID
|
||||
testNetworkID, // network ID
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey, // tx fee payer
|
||||
|
@ -582,7 +582,7 @@ func TestAddNonDefaultSubnetValidatorTxSemanticVerify(t *testing.T) {
|
|||
SortByStartTime: true,
|
||||
Txs: []TimedTx{tx},
|
||||
},
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
)
|
||||
// Node with ID nodeIDKey.PublicKey().Address() now pending validator for subnet with ID testSubnet1.ID
|
||||
|
||||
|
@ -604,7 +604,7 @@ func TestAddNonDefaultSubnetValidatorMarshal(t *testing.T) {
|
|||
uint64(defaultValidateStartTime.Unix()),
|
||||
uint64(defaultValidateEndTime.Unix()),
|
||||
defaultKey.PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
defaultKey,
|
||||
|
|
|
@ -105,15 +105,15 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
return nil, nil, nil, nil, err
|
||||
}
|
||||
for _, subnet := range subnets {
|
||||
current, pending, err := tx.vm.calculateValidators(db, tx.Timestamp(), subnet.ID)
|
||||
current, pending, err := tx.vm.calculateValidators(db, tx.Timestamp(), subnet.id)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, current, subnet.ID); err != nil {
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, current, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pending, subnet.ID); err != nil {
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pending, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
return
|
||||
}
|
||||
for _, subnet := range subnets {
|
||||
if err := tx.vm.updateValidators(subnet.ID); err != nil {
|
||||
if err := tx.vm.updateValidators(subnet.id); err != nil {
|
||||
tx.vm.Ctx.Log.Debug("failed to update validators on the default subnet: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ var (
|
|||
type AtomicTx interface {
|
||||
initialize(vm *VM) error
|
||||
|
||||
ID() ids.ID
|
||||
|
||||
// UTXOs this tx consumes
|
||||
InputUTXOs() ids.Set
|
||||
|
||||
|
|
|
@ -23,12 +23,6 @@ var (
|
|||
|
||||
// UnsignedCreateSubnetTx is an unsigned proposal to create a new subnet
|
||||
type UnsignedCreateSubnetTx struct {
|
||||
// The VM this tx exists within
|
||||
vm *VM
|
||||
|
||||
// ID is this transaction's ID
|
||||
ID ids.ID
|
||||
|
||||
// NetworkID is the ID of the network this tx was issued on
|
||||
NetworkID uint32 `serialize:"true"`
|
||||
|
||||
|
@ -47,6 +41,12 @@ type UnsignedCreateSubnetTx struct {
|
|||
type CreateSubnetTx struct {
|
||||
UnsignedCreateSubnetTx `serialize:"true"`
|
||||
|
||||
// The VM this tx exists within
|
||||
vm *VM
|
||||
|
||||
// ID is this transaction's ID
|
||||
id ids.ID
|
||||
|
||||
// The public key that signed this transaction
|
||||
// The transaction fee will be paid from the corresponding account
|
||||
// (ie the account whose ID is [key].Address())
|
||||
|
@ -60,6 +60,9 @@ type CreateSubnetTx struct {
|
|||
bytes []byte
|
||||
}
|
||||
|
||||
// ID returns the ID of this tx
|
||||
func (tx *CreateSubnetTx) ID() ids.ID { return tx.id }
|
||||
|
||||
// SyntacticVerify nil iff [tx] is syntactically valid.
|
||||
// If [tx] is valid, this method sets [tx.key]
|
||||
func (tx *CreateSubnetTx) SyntacticVerify() error {
|
||||
|
@ -68,7 +71,7 @@ func (tx *CreateSubnetTx) SyntacticVerify() error {
|
|||
return errNilTx
|
||||
case tx.key != nil:
|
||||
return nil // Only verify the transaction once
|
||||
case tx.ID.IsZero():
|
||||
case tx.id.IsZero():
|
||||
return errInvalidID
|
||||
case tx.NetworkID != tx.vm.Ctx.NetworkID:
|
||||
return errWrongNetworkID
|
||||
|
@ -106,8 +109,8 @@ func (tx *CreateSubnetTx) SemanticVerify(db database.Database) (func(), error) {
|
|||
}
|
||||
|
||||
for _, subnet := range subnets {
|
||||
if subnet.ID.Equals(tx.ID) {
|
||||
return nil, fmt.Errorf("there is already a subnet with ID %s", tx.ID)
|
||||
if subnet.id.Equals(tx.id) {
|
||||
return nil, fmt.Errorf("there is already a subnet with ID %s", tx.id)
|
||||
}
|
||||
}
|
||||
subnets = append(subnets, tx) // add new subnet
|
||||
|
@ -152,7 +155,7 @@ func (tx *CreateSubnetTx) initialize(vm *VM) error {
|
|||
return err
|
||||
}
|
||||
tx.bytes = txBytes
|
||||
tx.ID = ids.NewID(hashing.ComputeHash256Array(txBytes))
|
||||
tx.id = ids.NewID(hashing.ComputeHash256Array(txBytes))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -160,15 +163,12 @@ func (vm *VM) newCreateSubnetTx(networkID uint32, nonce uint64, controlKeys []id
|
|||
threshold uint16, payerKey *crypto.PrivateKeySECP256K1R,
|
||||
) (*CreateSubnetTx, error) {
|
||||
|
||||
tx := &CreateSubnetTx{
|
||||
UnsignedCreateSubnetTx: UnsignedCreateSubnetTx{
|
||||
vm: vm,
|
||||
NetworkID: networkID,
|
||||
Nonce: nonce,
|
||||
ControlKeys: controlKeys,
|
||||
Threshold: threshold,
|
||||
},
|
||||
}
|
||||
tx := &CreateSubnetTx{UnsignedCreateSubnetTx: UnsignedCreateSubnetTx{
|
||||
NetworkID: networkID,
|
||||
Nonce: nonce,
|
||||
ControlKeys: controlKeys,
|
||||
Threshold: threshold,
|
||||
}}
|
||||
|
||||
unsignedIntf := interface{}(&tx.UnsignedCreateSubnetTx)
|
||||
unsignedBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
|
|
|
@ -38,7 +38,7 @@ type UnsignedImportTx struct {
|
|||
Nonce uint64 `serialize:"true"`
|
||||
|
||||
// Account that this transaction is being sent by. This is needed to ensure the Credentials are replay safe.
|
||||
Account [crypto.SECP256K1RPKLen]byte `serialize:"true"`
|
||||
Account ids.ShortID `serialize:"true"`
|
||||
|
||||
Ins []*ava.TransferableInput `serialize:"true"` // The inputs to this transaction
|
||||
}
|
||||
|
@ -129,17 +129,12 @@ func (tx *ImportTx) SyntacticVerify() error {
|
|||
return err
|
||||
}
|
||||
|
||||
expectedPublicKey, err := tx.vm.factory.ToPublicKey(tx.Account[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := tx.vm.factory.RecoverPublicKey(unsignedBytes, tx.Sig[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !expectedPublicKey.Address().Equals(key.Address()) {
|
||||
if !tx.Account.Equals(key.Address()) {
|
||||
return errPublicKeySignatureMismatch
|
||||
}
|
||||
|
||||
|
@ -236,12 +231,10 @@ func (vm *VM) newImportTx(nonce uint64, networkID uint32, ins []*ava.Transferabl
|
|||
tx := &ImportTx{UnsignedImportTx: UnsignedImportTx{
|
||||
NetworkID: networkID,
|
||||
Nonce: nonce,
|
||||
Account: key.PublicKey().Address(),
|
||||
Ins: ins,
|
||||
}}
|
||||
|
||||
pubkeyBytes := key.PublicKey().Bytes()
|
||||
copy(tx.Account[:], pubkeyBytes)
|
||||
|
||||
unsignedIntf := interface{}(&tx.UnsignedImportTx)
|
||||
unsignedBytes, err := Codec.Marshal(&unsignedIntf) // Byte repr. of unsigned transaction
|
||||
if err != nil {
|
||||
|
|
|
@ -16,7 +16,11 @@ import (
|
|||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils/crypto"
|
||||
"github.com/ava-labs/gecko/utils/formatting"
|
||||
"github.com/ava-labs/gecko/utils/hashing"
|
||||
"github.com/ava-labs/gecko/utils/json"
|
||||
"github.com/ava-labs/gecko/utils/math"
|
||||
"github.com/ava-labs/gecko/vms/components/ava"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -97,7 +101,7 @@ func (service *Service) GetSubnets(_ *http.Request, args *GetSubnetsArgs, respon
|
|||
response.Subnets = make([]APISubnet, len(subnets))
|
||||
for i, subnet := range subnets {
|
||||
response.Subnets[i] = APISubnet{
|
||||
ID: subnet.ID,
|
||||
ID: subnet.id,
|
||||
ControlKeys: subnet.ControlKeys,
|
||||
Threshold: json.Uint16(subnet.Threshold),
|
||||
}
|
||||
|
@ -108,10 +112,10 @@ func (service *Service) GetSubnets(_ *http.Request, args *GetSubnetsArgs, respon
|
|||
idsSet := ids.Set{}
|
||||
idsSet.Add(args.IDs...)
|
||||
for _, subnet := range subnets {
|
||||
if idsSet.Contains(subnet.ID) {
|
||||
if idsSet.Contains(subnet.id) {
|
||||
response.Subnets = append(response.Subnets,
|
||||
APISubnet{
|
||||
ID: subnet.ID,
|
||||
ID: subnet.id,
|
||||
ControlKeys: subnet.ControlKeys,
|
||||
Threshold: json.Uint16(subnet.Threshold),
|
||||
},
|
||||
|
@ -432,6 +436,11 @@ type genericTx struct {
|
|||
******************************************************
|
||||
*/
|
||||
|
||||
// CreateTxResponse is the response from calls to create a transaction
|
||||
type CreateTxResponse struct {
|
||||
UnsignedTx formatting.CB58 `json:"unsignedTx"`
|
||||
}
|
||||
|
||||
// AddDefaultSubnetValidatorArgs are the arguments to AddDefaultSubnetValidator
|
||||
type AddDefaultSubnetValidatorArgs struct {
|
||||
APIDefaultSubnetValidator
|
||||
|
@ -440,15 +449,9 @@ type AddDefaultSubnetValidatorArgs struct {
|
|||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
}
|
||||
|
||||
// AddDefaultSubnetValidatorResponse is the response from a call to AddDefaultSubnetValidator
|
||||
type AddDefaultSubnetValidatorResponse struct {
|
||||
// The unsigned transaction
|
||||
UnsignedTx formatting.CB58 `json:"unsignedTx"`
|
||||
}
|
||||
|
||||
// AddDefaultSubnetValidator returns an unsigned transaction to add a validator to the default subnet
|
||||
// The returned unsigned transaction should be signed using Sign()
|
||||
func (service *Service) AddDefaultSubnetValidator(_ *http.Request, args *AddDefaultSubnetValidatorArgs, reply *AddDefaultSubnetValidatorResponse) error {
|
||||
func (service *Service) AddDefaultSubnetValidator(_ *http.Request, args *AddDefaultSubnetValidatorArgs, reply *CreateTxResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.AddDefaultSubnetValidator called")
|
||||
|
||||
if args.ID.IsZero() { // If ID unspecified, use this node's ID as validator ID
|
||||
|
@ -490,16 +493,10 @@ type AddDefaultSubnetDelegatorArgs struct {
|
|||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
}
|
||||
|
||||
// AddDefaultSubnetDelegatorResponse is the response from a call to AddDefaultSubnetDelegator
|
||||
type AddDefaultSubnetDelegatorResponse struct {
|
||||
// The unsigned transaction
|
||||
UnsignedTx formatting.CB58 `json:"unsignedTx"`
|
||||
}
|
||||
|
||||
// AddDefaultSubnetDelegator returns an unsigned transaction to add a delegator
|
||||
// to the default subnet
|
||||
// The returned unsigned transaction should be signed using Sign()
|
||||
func (service *Service) AddDefaultSubnetDelegator(_ *http.Request, args *AddDefaultSubnetDelegatorArgs, reply *AddDefaultSubnetDelegatorResponse) error {
|
||||
func (service *Service) AddDefaultSubnetDelegator(_ *http.Request, args *AddDefaultSubnetDelegatorArgs, reply *CreateTxResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.AddDefaultSubnetDelegator called")
|
||||
|
||||
if args.ID.IsZero() { // If ID unspecified, use this node's ID as validator ID
|
||||
|
@ -541,15 +538,9 @@ type AddNonDefaultSubnetValidatorArgs struct {
|
|||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
}
|
||||
|
||||
// AddNonDefaultSubnetValidatorResponse is the response from a call to AddNonDefaultSubnetValidator
|
||||
type AddNonDefaultSubnetValidatorResponse struct {
|
||||
// The unsigned transaction
|
||||
UnsignedTx formatting.CB58 `json:"unsignedTx"`
|
||||
}
|
||||
|
||||
// AddNonDefaultSubnetValidator adds a validator to a subnet other than the default subnet
|
||||
// Returns the unsigned transaction, which must be signed using Sign
|
||||
func (service *Service) AddNonDefaultSubnetValidator(_ *http.Request, args *AddNonDefaultSubnetValidatorArgs, response *AddNonDefaultSubnetValidatorResponse) error {
|
||||
func (service *Service) AddNonDefaultSubnetValidator(_ *http.Request, args *AddNonDefaultSubnetValidatorArgs, response *CreateTxResponse) error {
|
||||
tx := addNonDefaultSubnetValidatorTx{
|
||||
UnsignedAddNonDefaultSubnetValidatorTx: UnsignedAddNonDefaultSubnetValidatorTx{
|
||||
SubnetValidator: SubnetValidator{
|
||||
|
@ -583,6 +574,83 @@ func (service *Service) AddNonDefaultSubnetValidator(_ *http.Request, args *AddN
|
|||
return nil
|
||||
}
|
||||
|
||||
// CreateSubnetArgs are the arguments to CreateSubnet
|
||||
type CreateSubnetArgs struct {
|
||||
// The ID member of APISubnet is ignored
|
||||
APISubnet
|
||||
|
||||
// Nonce of the account that pays the transaction fee
|
||||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
}
|
||||
|
||||
// CreateSubnet returns an unsigned transaction to create a new subnet.
|
||||
// The unsigned transaction must be signed with the key of [args.Payer]
|
||||
func (service *Service) CreateSubnet(_ *http.Request, args *CreateSubnetArgs, response *CreateTxResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.createSubnet called")
|
||||
|
||||
// Create the transaction
|
||||
tx := CreateSubnetTx{
|
||||
UnsignedCreateSubnetTx: UnsignedCreateSubnetTx{
|
||||
NetworkID: service.vm.Ctx.NetworkID,
|
||||
Nonce: uint64(args.PayerNonce),
|
||||
ControlKeys: args.ControlKeys,
|
||||
Threshold: uint16(args.Threshold),
|
||||
},
|
||||
key: nil,
|
||||
Sig: [65]byte{},
|
||||
bytes: nil,
|
||||
}
|
||||
|
||||
txBytes, err := Codec.Marshal(genericTx{Tx: &tx})
|
||||
if err != nil {
|
||||
return errCreatingTransaction
|
||||
}
|
||||
|
||||
response.UnsignedTx.Bytes = txBytes
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateExportTxArgs are the arguments to CreateExportTx
|
||||
type CreateExportTxArgs struct {
|
||||
// ID of the address that will receive the exported funds
|
||||
To ids.ShortID `json:"to"`
|
||||
|
||||
// Nonce of the account that pays the transaction fee
|
||||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
|
||||
Amount json.Uint64 `json:"amount"`
|
||||
}
|
||||
|
||||
// CreateExportTx returns an unsigned transaction to export funds.
|
||||
// The unsigned transaction must be signed with the key of [args.Payer]
|
||||
func (service *Service) CreateExportTx(_ *http.Request, args *CreateExportTxArgs, response *CreateTxResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.createExportTx called")
|
||||
|
||||
// Create the transaction
|
||||
tx := ExportTx{UnsignedExportTx: UnsignedExportTx{
|
||||
NetworkID: service.vm.Ctx.NetworkID,
|
||||
Nonce: uint64(args.PayerNonce),
|
||||
Outs: []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
Asset: ava.Asset{ID: service.vm.ava},
|
||||
Out: &secp256k1fx.TransferOutput{
|
||||
Amt: uint64(args.Amount),
|
||||
OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{args.To},
|
||||
},
|
||||
},
|
||||
}},
|
||||
}}
|
||||
|
||||
txBytes, err := Codec.Marshal(genericTx{Tx: &tx})
|
||||
if err != nil {
|
||||
return errCreatingTransaction
|
||||
}
|
||||
|
||||
response.UnsignedTx.Bytes = txBytes
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
******************************************************
|
||||
**************** Sign/Issue Txs **********************
|
||||
|
@ -606,7 +674,7 @@ type SignArgs struct {
|
|||
// SignResponse is the response from Sign
|
||||
type SignResponse struct {
|
||||
// The signed bytes
|
||||
Tx formatting.CB58
|
||||
Tx formatting.CB58 `json:"tx"`
|
||||
}
|
||||
|
||||
// Sign [args.bytes]
|
||||
|
@ -642,6 +710,8 @@ func (service *Service) Sign(_ *http.Request, args *SignArgs, reply *SignRespons
|
|||
genTx.Tx, err = service.signAddNonDefaultSubnetValidatorTx(tx, key)
|
||||
case *CreateSubnetTx:
|
||||
genTx.Tx, err = service.signCreateSubnetTx(tx, key)
|
||||
case *ExportTx:
|
||||
genTx.Tx, err = service.signExportTx(tx, key)
|
||||
default:
|
||||
err = errors.New("Could not parse given tx. Must be one of: addDefaultSubnetValidatorTx, addNonDefaultSubnetValidatorTx, createSubnetTx")
|
||||
}
|
||||
|
@ -722,6 +792,29 @@ func (service *Service) signCreateSubnetTx(tx *CreateSubnetTx, key *crypto.Priva
|
|||
return tx, nil
|
||||
}
|
||||
|
||||
// Sign [xt] with [key]
|
||||
func (service *Service) signExportTx(tx *ExportTx, key *crypto.PrivateKeySECP256K1R) (*ExportTx, error) {
|
||||
service.vm.Ctx.Log.Debug("platform.signAddDefaultSubnetValidatorTx called")
|
||||
|
||||
// TODO: Should we check if tx is already signed?
|
||||
unsignedIntf := interface{}(&tx.UnsignedExportTx)
|
||||
unsignedTxBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error serializing unsigned tx: %v", err)
|
||||
}
|
||||
|
||||
sig, err := key.Sign(unsignedTxBytes)
|
||||
if err != nil {
|
||||
return nil, errors.New("error while signing")
|
||||
}
|
||||
if len(sig) != crypto.SECP256K1RSigLen {
|
||||
return nil, fmt.Errorf("expected signature to be length %d but was length %d", crypto.SECP256K1RSigLen, len(sig))
|
||||
}
|
||||
copy(tx.Sig[:], sig)
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// Signs an unsigned or partially signed addNonDefaultSubnetValidatorTx with [key]
|
||||
// If [key] is a control key for the subnet and there is an empty spot in tx.ControlSigs, signs there
|
||||
// If [key] is a control key for the subnet and there is no empty spot in tx.ControlSigs, signs as payer
|
||||
|
@ -775,6 +868,141 @@ func (service *Service) signAddNonDefaultSubnetValidatorTx(tx *addNonDefaultSubn
|
|||
return tx, nil
|
||||
}
|
||||
|
||||
// CreateImportTxArgs are the arguments to CreateImportTx
|
||||
type CreateImportTxArgs struct {
|
||||
// Addresses that can be used to sign the import
|
||||
ImportAddresses []ids.ShortID `json:"importAddresses"`
|
||||
|
||||
// ID of the account that will receive the imported funds, and pay the
|
||||
// import fee
|
||||
AccountID ids.ShortID `json:"accountID"`
|
||||
|
||||
// Nonce of the account that pays the transaction fee
|
||||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
|
||||
// User that controls the Addresses
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// CreateImportTx returns an unsigned transaction to import funds.
|
||||
// The unsigned transaction must be signed with the key of [args.Payer]
|
||||
func (service *Service) CreateImportTx(_ *http.Request, args *CreateImportTxArgs, response *SignResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.createImportTx called")
|
||||
|
||||
// Get the key of the Signer
|
||||
db, err := service.vm.Ctx.Keystore.GetDatabase(args.Username, args.Password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't get data for user '%s'. Does user exist?", args.Username)
|
||||
}
|
||||
user := user{db: db}
|
||||
|
||||
kc := secp256k1fx.NewKeychain()
|
||||
for _, addr := range args.ImportAddresses {
|
||||
key, err := user.getKey(addr)
|
||||
if err != nil {
|
||||
return errDB
|
||||
}
|
||||
kc.Add(key)
|
||||
}
|
||||
|
||||
key, err := user.getKey(args.AccountID)
|
||||
if err != nil {
|
||||
return errDB
|
||||
}
|
||||
kc.Add(key)
|
||||
|
||||
addrs := ids.Set{}
|
||||
for _, addr := range args.ImportAddresses {
|
||||
addrs.Add(ids.NewID(hashing.ComputeHash256Array(addr.Bytes())))
|
||||
}
|
||||
|
||||
utxos, err := service.vm.GetAtomicUTXOs(addrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem retrieving user's atomic UTXOs: %w", err)
|
||||
}
|
||||
|
||||
amount := uint64(0)
|
||||
time := service.vm.clock.Unix()
|
||||
|
||||
ins := []*ava.TransferableInput{}
|
||||
keys := [][]*crypto.PrivateKeySECP256K1R{}
|
||||
for _, utxo := range utxos {
|
||||
if !utxo.AssetID().Equals(service.vm.ava) {
|
||||
continue
|
||||
}
|
||||
inputIntf, signers, err := kc.Spend(utxo.Out, time)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
input, ok := inputIntf.(ava.Transferable)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
spent, err := math.Add64(amount, input.Amount())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount = spent
|
||||
|
||||
in := &ava.TransferableInput{
|
||||
UTXOID: utxo.UTXOID,
|
||||
Asset: ava.Asset{ID: service.vm.ava},
|
||||
In: input,
|
||||
}
|
||||
|
||||
ins = append(ins, in)
|
||||
keys = append(keys, signers)
|
||||
}
|
||||
|
||||
ava.SortTransferableInputsWithSigners(ins, keys)
|
||||
|
||||
// Create the transaction
|
||||
tx := ImportTx{UnsignedImportTx: UnsignedImportTx{
|
||||
NetworkID: service.vm.Ctx.NetworkID,
|
||||
Nonce: uint64(args.PayerNonce),
|
||||
Account: args.AccountID,
|
||||
Ins: ins,
|
||||
}}
|
||||
|
||||
// TODO: Should we check if tx is already signed?
|
||||
unsignedIntf := interface{}(&tx.UnsignedImportTx)
|
||||
unsignedTxBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error serializing unsigned tx: %w", err)
|
||||
}
|
||||
hash := hashing.ComputeHash256(unsignedTxBytes)
|
||||
|
||||
sig, err := key.SignHash(unsignedTxBytes)
|
||||
if err != nil {
|
||||
return errors.New("error while signing")
|
||||
}
|
||||
copy(tx.Sig[:], sig)
|
||||
|
||||
for _, credKeys := range keys {
|
||||
cred := &secp256k1fx.Credential{}
|
||||
for _, key := range credKeys {
|
||||
sig, err := key.SignHash(hash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem creating transaction: %w", err)
|
||||
}
|
||||
fixedSig := [crypto.SECP256K1RSigLen]byte{}
|
||||
copy(fixedSig[:], sig)
|
||||
|
||||
cred.Sigs = append(cred.Sigs, fixedSig)
|
||||
}
|
||||
tx.Creds = append(tx.Creds, cred)
|
||||
}
|
||||
|
||||
txBytes, err := Codec.Marshal(genericTx{Tx: &tx})
|
||||
if err != nil {
|
||||
return errCreatingTransaction
|
||||
}
|
||||
|
||||
response.Tx.Bytes = txBytes
|
||||
return nil
|
||||
}
|
||||
|
||||
// IssueTxArgs are the arguments to IssueTx
|
||||
type IssueTxArgs struct {
|
||||
// Tx being sent to the network
|
||||
|
@ -800,69 +1028,25 @@ func (service *Service) IssueTx(_ *http.Request, args *IssueTxArgs, response *Is
|
|||
return fmt.Errorf("error initializing tx: %s", err)
|
||||
}
|
||||
service.vm.unissuedEvents.Push(tx)
|
||||
defer service.vm.resetTimer()
|
||||
response.TxID = tx.ID()
|
||||
return nil
|
||||
case *CreateSubnetTx:
|
||||
case DecisionTx:
|
||||
if err := tx.initialize(service.vm); err != nil {
|
||||
return fmt.Errorf("error initializing tx: %s", err)
|
||||
}
|
||||
service.vm.unissuedDecisionTxs = append(service.vm.unissuedDecisionTxs, tx)
|
||||
defer service.vm.resetTimer()
|
||||
response.TxID = tx.ID
|
||||
return nil
|
||||
response.TxID = tx.ID()
|
||||
case AtomicTx:
|
||||
if err := tx.initialize(service.vm); err != nil {
|
||||
return fmt.Errorf("error initializing tx: %s", err)
|
||||
}
|
||||
service.vm.unissuedAtomicTxs = append(service.vm.unissuedAtomicTxs, tx)
|
||||
response.TxID = tx.ID()
|
||||
default:
|
||||
return errors.New("Could not parse given tx. Must be one of: addDefaultSubnetValidatorTx, addDefaultSubnetDelegatorTx, addNonDefaultSubnetValidatorTx, createSubnetTx")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
******************************************************
|
||||
**************** Create a Subnet *********************
|
||||
******************************************************
|
||||
*/
|
||||
|
||||
// CreateSubnetArgs are the arguments to CreateSubnet
|
||||
type CreateSubnetArgs struct {
|
||||
// The ID member of APISubnet is ignored
|
||||
APISubnet
|
||||
|
||||
// Nonce of the account that pays the transaction fee
|
||||
PayerNonce json.Uint64 `json:"payerNonce"`
|
||||
}
|
||||
|
||||
// CreateSubnetResponse is the response from a call to CreateSubnet
|
||||
type CreateSubnetResponse struct {
|
||||
// Byte representation of the unsigned transaction to create a new subnet
|
||||
UnsignedTx formatting.CB58 `json:"unsignedTx"`
|
||||
}
|
||||
|
||||
// CreateSubnet returns an unsigned transaction to create a new subnet.
|
||||
// The unsigned transaction must be signed with the key of [args.Payer]
|
||||
func (service *Service) CreateSubnet(_ *http.Request, args *CreateSubnetArgs, response *CreateSubnetResponse) error {
|
||||
service.vm.Ctx.Log.Debug("platform.createSubnet called")
|
||||
|
||||
// Create the transaction
|
||||
tx := CreateSubnetTx{
|
||||
UnsignedCreateSubnetTx: UnsignedCreateSubnetTx{
|
||||
NetworkID: service.vm.Ctx.NetworkID,
|
||||
Nonce: uint64(args.PayerNonce),
|
||||
ControlKeys: args.ControlKeys,
|
||||
Threshold: uint16(args.Threshold),
|
||||
},
|
||||
key: nil,
|
||||
Sig: [65]byte{},
|
||||
bytes: nil,
|
||||
return errors.New("Could not parse given tx. Must be a TimedTx, DecisionTx, or AtomicTx")
|
||||
}
|
||||
|
||||
txBytes, err := Codec.Marshal(genericTx{Tx: &tx})
|
||||
if err != nil {
|
||||
return errCreatingTransaction
|
||||
}
|
||||
|
||||
response.UnsignedTx.Bytes = txBytes
|
||||
service.vm.resetTimer()
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1028,3 +1212,176 @@ func (service *Service) chainExists(blockID ids.ID, chainID ids.ID) (bool, error
|
|||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// // SendExportArgs are arguments for passing into SendExport requests
|
||||
// type SendExportArgs struct {
|
||||
// Username string `json:"username"`
|
||||
// Password string `json:"password"`
|
||||
// Amount json.Uint64 `json:"amount"`
|
||||
// To string `json:"to"`
|
||||
// }
|
||||
|
||||
// // SendExportReply defines the Send replies returned from the API
|
||||
// type SendExportReply struct {
|
||||
// TxID ids.ID `json:"txID"`
|
||||
// }
|
||||
|
||||
// // SendExport returns the ID of the newly created atomic transaction
|
||||
// func (service *Service) SendExport(_ *http.Request, args *SendExportArgs, reply *SendExportReply) error {
|
||||
// service.vm.ctx.Log.Verbo("SendExport called with username: %s", args.Username)
|
||||
|
||||
// if args.Amount == 0 {
|
||||
// return errInvalidAmount
|
||||
// }
|
||||
|
||||
// toBytes, err := service.vm.Parse(args.To)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem parsing to address: %w", err)
|
||||
// }
|
||||
// to, err := ids.ToShortID(toBytes)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem parsing to address: %w", err)
|
||||
// }
|
||||
|
||||
// db, err := service.vm.ctx.Keystore.GetDatabase(args.Username, args.Password)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem retrieving user: %w", err)
|
||||
// }
|
||||
|
||||
// user := userState{vm: service.vm}
|
||||
|
||||
// addresses, _ := user.Addresses(db)
|
||||
|
||||
// addrs := ids.Set{}
|
||||
// addrs.Add(addresses...)
|
||||
// utxos, err := service.vm.GetUTXOs(addrs)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem retrieving user's UTXOs: %w", err)
|
||||
// }
|
||||
|
||||
// kc := secp256k1fx.NewKeychain()
|
||||
// for _, addr := range addresses {
|
||||
// sk, err := user.Key(db, addr)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem retrieving private key: %w", err)
|
||||
// }
|
||||
// kc.Add(sk)
|
||||
// }
|
||||
|
||||
// amountSpent := uint64(0)
|
||||
// time := service.vm.clock.Unix()
|
||||
|
||||
// ins := []*ava.TransferableInput{}
|
||||
// keys := [][]*crypto.PrivateKeySECP256K1R{}
|
||||
// for _, utxo := range utxos {
|
||||
// if !utxo.AssetID().Equals(service.vm.ava) {
|
||||
// continue
|
||||
// }
|
||||
// inputIntf, signers, err := kc.Spend(utxo.Out, time)
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// input, ok := inputIntf.(ava.Transferable)
|
||||
// if !ok {
|
||||
// continue
|
||||
// }
|
||||
// spent, err := math.Add64(amountSpent, input.Amount())
|
||||
// if err != nil {
|
||||
// return errSpendOverflow
|
||||
// }
|
||||
// amountSpent = spent
|
||||
|
||||
// in := &ava.TransferableInput{
|
||||
// UTXOID: utxo.UTXOID,
|
||||
// Asset: ava.Asset{ID: service.vm.ava},
|
||||
// In: input,
|
||||
// }
|
||||
|
||||
// ins = append(ins, in)
|
||||
// keys = append(keys, signers)
|
||||
|
||||
// if amountSpent >= uint64(args.Amount) {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
// if amountSpent < uint64(args.Amount) {
|
||||
// return errInsufficientFunds
|
||||
// }
|
||||
|
||||
// ava.SortTransferableInputsWithSigners(ins, keys)
|
||||
|
||||
// exportOuts := []*ava.TransferableOutput{&ava.TransferableOutput{
|
||||
// Asset: ava.Asset{ID: service.vm.ava},
|
||||
// Out: &secp256k1fx.TransferOutput{
|
||||
// Amt: uint64(args.Amount),
|
||||
// Locktime: 0,
|
||||
// OutputOwners: secp256k1fx.OutputOwners{
|
||||
// Threshold: 1,
|
||||
// Addrs: []ids.ShortID{to},
|
||||
// },
|
||||
// },
|
||||
// }}
|
||||
|
||||
// outs := []*ava.TransferableOutput{}
|
||||
// if amountSpent > uint64(args.Amount) {
|
||||
// changeAddr := kc.Keys[0].PublicKey().Address()
|
||||
// outs = append(outs, &ava.TransferableOutput{
|
||||
// Asset: ava.Asset{ID: service.vm.ava},
|
||||
// Out: &secp256k1fx.TransferOutput{
|
||||
// Amt: amountSpent - uint64(args.Amount),
|
||||
// Locktime: 0,
|
||||
// OutputOwners: secp256k1fx.OutputOwners{
|
||||
// Threshold: 1,
|
||||
// Addrs: []ids.ShortID{changeAddr},
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
|
||||
// ava.SortTransferableOutputs(outs, service.vm.codec)
|
||||
|
||||
// tx := Tx{UnsignedTx: &ExportTx{
|
||||
// BaseTx: BaseTx{
|
||||
// NetID: service.vm.ctx.NetworkID,
|
||||
// BCID: service.vm.ctx.ChainID,
|
||||
// Outs: outs,
|
||||
// Ins: ins,
|
||||
// },
|
||||
// Outs: exportOuts,
|
||||
// }}
|
||||
|
||||
// unsignedBytes, err := service.vm.codec.Marshal(&tx.UnsignedTx)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem creating transaction: %w", err)
|
||||
// }
|
||||
// hash := hashing.ComputeHash256(unsignedBytes)
|
||||
|
||||
// for _, credKeys := range keys {
|
||||
// cred := &secp256k1fx.Credential{}
|
||||
// for _, key := range credKeys {
|
||||
// sig, err := key.SignHash(hash)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem creating transaction: %w", err)
|
||||
// }
|
||||
// fixedSig := [crypto.SECP256K1RSigLen]byte{}
|
||||
// copy(fixedSig[:], sig)
|
||||
|
||||
// cred.Sigs = append(cred.Sigs, fixedSig)
|
||||
// }
|
||||
// tx.Creds = append(tx.Creds, cred)
|
||||
// }
|
||||
|
||||
// b, err := service.vm.codec.Marshal(tx)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem creating transaction: %w", err)
|
||||
// }
|
||||
|
||||
// txID, err := service.vm.IssueTx(b, nil)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("problem issuing transaction: %w", err)
|
||||
// }
|
||||
|
||||
// reply.TxID = txID
|
||||
// return nil
|
||||
// }
|
||||
|
|
|
@ -12,6 +12,8 @@ import (
|
|||
|
||||
// DecisionTx is an operation that can be decided without being proposed
|
||||
type DecisionTx interface {
|
||||
ID() ids.ID
|
||||
|
||||
initialize(vm *VM) error
|
||||
|
||||
// Attempt to verify this transaction with the provided state. The provided
|
||||
|
|
|
@ -211,18 +211,18 @@ func (vm *VM) getSubnets(db database.Database) ([]*CreateSubnetTx, error) {
|
|||
}
|
||||
|
||||
// get the subnet with the specified ID
|
||||
func (vm *VM) getSubnet(db database.Database, ID ids.ID) (*CreateSubnetTx, error) {
|
||||
func (vm *VM) getSubnet(db database.Database, id ids.ID) (*CreateSubnetTx, error) {
|
||||
subnets, err := vm.getSubnets(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, subnet := range subnets {
|
||||
if subnet.ID.Equals(ID) {
|
||||
if subnet.id.Equals(id) {
|
||||
return subnet, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("couldn't find subnet with ID %s", ID)
|
||||
return nil, fmt.Errorf("couldn't find subnet with ID %s", id)
|
||||
}
|
||||
|
||||
// register each type that we'll be storing in the database
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/ava-labs/gecko/utils/timer"
|
||||
"github.com/ava-labs/gecko/utils/units"
|
||||
"github.com/ava-labs/gecko/utils/wrappers"
|
||||
"github.com/ava-labs/gecko/vms/components/ava"
|
||||
"github.com/ava-labs/gecko/vms/components/codec"
|
||||
"github.com/ava-labs/gecko/vms/components/core"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
|
@ -632,7 +633,7 @@ func (vm *VM) nextValidatorChangeTime(db database.Database, start bool) time.Tim
|
|||
return earliest
|
||||
}
|
||||
for _, subnet := range subnets {
|
||||
t := vm.nextSubnetValidatorChangeTime(db, subnet.ID, start)
|
||||
t := vm.nextSubnetValidatorChangeTime(db, subnet.id, start)
|
||||
if t.Before(earliest) {
|
||||
earliest = t
|
||||
}
|
||||
|
@ -740,3 +741,28 @@ func (vm *VM) Codec() codec.Codec { return vm.codec }
|
|||
|
||||
// Clock ...
|
||||
func (vm *VM) Clock() *timer.Clock { return &vm.clock }
|
||||
|
||||
// GetAtomicUTXOs returns the utxos that at least one of the provided addresses is
|
||||
// referenced in.
|
||||
func (vm *VM) GetAtomicUTXOs(addrs ids.Set) ([]*ava.UTXO, error) {
|
||||
smDB := vm.Ctx.SharedMemory.GetDatabase(vm.avm)
|
||||
defer vm.Ctx.SharedMemory.ReleaseDatabase(vm.avm)
|
||||
|
||||
state := ava.NewPrefixedState(smDB, vm.codec)
|
||||
|
||||
utxoIDs := ids.Set{}
|
||||
for _, addr := range addrs.List() {
|
||||
utxos, _ := state.AVMFunds(addr)
|
||||
utxoIDs.Add(utxos...)
|
||||
}
|
||||
|
||||
utxos := []*ava.UTXO{}
|
||||
for _, utxoID := range utxoIDs.List() {
|
||||
utxo, err := state.AVMUTXO(utxoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
utxos = append(utxos, utxo)
|
||||
}
|
||||
return utxos, nil
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ func defaultVM() *VM {
|
|||
&EventHeap{
|
||||
SortByStartTime: false,
|
||||
},
|
||||
tx.ID,
|
||||
tx.id,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -163,7 +163,7 @@ func defaultVM() *VM {
|
|||
&EventHeap{
|
||||
SortByStartTime: true,
|
||||
},
|
||||
tx.ID,
|
||||
tx.id,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -437,7 +437,7 @@ func TestAddNonDefaultSubnetValidatorAccept(t *testing.T) {
|
|||
uint64(startTime.Unix()),
|
||||
uint64(endTime.Unix()),
|
||||
keys[0].PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
||||
keys[0],
|
||||
|
@ -482,7 +482,7 @@ func TestAddNonDefaultSubnetValidatorAccept(t *testing.T) {
|
|||
commit.Accept() // accept the proposal
|
||||
|
||||
// Verify that new validator is in pending validator set
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, testSubnet1.ID)
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, testSubnet1.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ func TestAddNonDefaultSubnetValidatorReject(t *testing.T) {
|
|||
uint64(startTime.Unix()),
|
||||
uint64(endTime.Unix()),
|
||||
keys[0].PublicKey().Address(),
|
||||
testSubnet1.ID,
|
||||
testSubnet1.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[1], testSubnet1ControlKeys[2]},
|
||||
keys[0],
|
||||
|
@ -555,7 +555,7 @@ func TestAddNonDefaultSubnetValidatorReject(t *testing.T) {
|
|||
abort.Accept() // reject the proposal
|
||||
|
||||
// Verify that new validator NOT in pending validator set
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, testSubnet1.ID)
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, testSubnet1.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -885,7 +885,7 @@ func TestCreateSubnet(t *testing.T) {
|
|||
uint64(startTime.Unix()),
|
||||
uint64(endTime.Unix()),
|
||||
keys[0].PublicKey().Address(),
|
||||
createSubnetTx.ID,
|
||||
createSubnetTx.id,
|
||||
testNetworkID,
|
||||
[]*crypto.PrivateKeySECP256K1R{keys[0]},
|
||||
keys[0],
|
||||
|
@ -935,7 +935,7 @@ func TestCreateSubnet(t *testing.T) {
|
|||
commit.Accept() // add the validator to pending validator set
|
||||
|
||||
// Verify validator is in pending validator set
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, createSubnetTx.ID)
|
||||
pendingValidators, err := vm.getPendingValidators(vm.DB, createSubnetTx.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -989,7 +989,7 @@ func TestCreateSubnet(t *testing.T) {
|
|||
|
||||
// Verify validator no longer in pending validator set
|
||||
// Verify validator is in pending validator set
|
||||
pendingValidators, err = vm.getPendingValidators(vm.DB, createSubnetTx.ID)
|
||||
pendingValidators, err = vm.getPendingValidators(vm.DB, createSubnetTx.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -998,7 +998,7 @@ func TestCreateSubnet(t *testing.T) {
|
|||
}
|
||||
|
||||
// Verify validator is in current validator set
|
||||
currentValidators, err := vm.getCurrentValidators(vm.DB, createSubnetTx.ID)
|
||||
currentValidators, err := vm.getCurrentValidators(vm.DB, createSubnetTx.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1048,14 +1048,14 @@ func TestCreateSubnet(t *testing.T) {
|
|||
commit.Accept() // remove validator from current validator set
|
||||
|
||||
// pending validators and current validator should be empty
|
||||
pendingValidators, err = vm.getPendingValidators(vm.DB, createSubnetTx.ID)
|
||||
pendingValidators, err = vm.getPendingValidators(vm.DB, createSubnetTx.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pendingValidators.Len() != 0 {
|
||||
t.Fatal("pending validator set should be empty")
|
||||
}
|
||||
currentValidators, err = vm.getCurrentValidators(vm.DB, createSubnetTx.ID)
|
||||
currentValidators, err = vm.getCurrentValidators(vm.DB, createSubnetTx.id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue