Donate tokens to attested machines so that these are able to run after their attestation (#375)

* added donation of tokens/denom to the just attestet machine
* extended the machine module to have two additional parameters: amount of tokens to be distributed and their denominator

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2024-04-23 12:00:31 +02:00 committed by GitHub
parent 5e2b307a70
commit 43d152fcf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 170 additions and 27 deletions

View File

@ -47644,6 +47644,11 @@ paths:
type: string type: string
asset_registry_path: asset_registry_path:
type: string type: string
dao_machine_funding_amount:
type: string
format: uint64
dao_machine_funding_denom:
type: string
description: >- description: >-
QueryParamsResponse is response type for the Query/Params RPC QueryParamsResponse is response type for the Query/Params RPC
method. method.
@ -77177,6 +77182,11 @@ definitions:
type: string type: string
asset_registry_path: asset_registry_path:
type: string type: string
dao_machine_funding_amount:
type: string
format: uint64
dao_machine_funding_denom:
type: string
description: Params defines the parameters for the module. description: Params defines the parameters for the module.
planetmintgo.machine.QueryGetLiquidAssetsByMachineidResponse: planetmintgo.machine.QueryGetLiquidAssetsByMachineidResponse:
type: object type: object
@ -77300,6 +77310,11 @@ definitions:
type: string type: string
asset_registry_path: asset_registry_path:
type: string type: string
dao_machine_funding_amount:
type: string
format: uint64
dao_machine_funding_denom:
type: string
description: QueryParamsResponse is response type for the Query/Params RPC method. description: QueryParamsResponse is response type for the Query/Params RPC method.
planetmintgo.machine.TrustAnchor: planetmintgo.machine.TrustAnchor:
type: object type: object

View File

@ -11,4 +11,6 @@ message Params {
string asset_registry_scheme =1; string asset_registry_scheme =1;
string asset_registry_domain =2; string asset_registry_domain =2;
string asset_registry_path =3; string asset_registry_path =3;
uint64 dao_machine_funding_amount = 4;
string dao_machine_funding_denom = 5;
} }

View File

@ -88,6 +88,7 @@ func (s *E2ETestSuite) TestAttestMachine() {
err = lib.ErrTypeAssertionFailed err = lib.ErrTypeAssertionFailed
s.Require().NoError(err) s.Require().NoError(err)
} }
assert.Contains(s.T(), preAttestationBalance.String(), "10000")
machine := moduleobject.Machine(sample.Name, pubKey, prvKey, addr.String()) machine := moduleobject.Machine(sample.Name, pubKey, prvKey, addr.String())
msg2 := machinetypes.NewMsgAttestMachine(addr.String(), &machine) msg2 := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
@ -98,6 +99,7 @@ func (s *E2ETestSuite) TestAttestMachine() {
s.Require().NoError(s.network.WaitForNextBlock()) s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(s.network.WaitForNextBlock()) s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(s.network.WaitForNextBlock()) s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(s.network.WaitForNextBlock())
rawLog, err = clitestutil.GetRawLogFromTxOut(val, out) rawLog, err = clitestutil.GetRawLogFromTxOut(val, out)
s.Require().NoError(err) s.Require().NoError(err)
@ -119,7 +121,7 @@ func (s *E2ETestSuite) TestAttestMachine() {
assert.Contains(s.T(), txResp.TxHash, txResponse.TxHash) assert.Contains(s.T(), txResp.TxHash, txResponse.TxHash)
s.Require().NoError(err) s.Require().NoError(err)
// Check postAttestationBalance as it should be the same as prior to the machine attestation // Check postAttestationBalance it should be the preAttestationBalance + th 8800 tokens being donated to the machine (no fees are taken)
postAttestationBalanceOutput, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{ postAttestationBalanceOutput, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
addr.String(), addr.String(),
}) })
@ -129,8 +131,7 @@ func (s *E2ETestSuite) TestAttestMachine() {
err = lib.ErrTypeAssertionFailed err = lib.ErrTypeAssertionFailed
s.Require().NoError(err) s.Require().NoError(err)
} }
assert.Contains(s.T(), postAttestationBalance.String(), "18800")
assert.Equal(s.T(), preAttestationBalance, postAttestationBalance)
} }
func (s *E2ETestSuite) TestInvalidAttestMachine() { func (s *E2ETestSuite) TestInvalidAttestMachine() {

View File

@ -4,6 +4,7 @@ import (
"context" "context"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/planetmint/planetmint-go/config" "github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/lib" "github.com/planetmint/planetmint-go/lib"
daotypes "github.com/planetmint/planetmint-go/x/dao/types" daotypes "github.com/planetmint/planetmint-go/x/dao/types"
@ -99,3 +100,15 @@ func SendUpdateRedeemClaim(goCtx context.Context, beneficiary string, id uint64,
loggingContext := "redeem claim" loggingContext := "redeem claim"
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg) buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
} }
func SendTokens(goCtx context.Context, beneficiary sdk.AccAddress, amount uint64, denominator string) {
sendingValidatorAddress := config.GetConfig().ValidatorAddress
coin := sdk.NewCoin(denominator, sdk.NewIntFromUint64(amount))
coins := sdk.NewCoins(coin)
orgAddr := sdk.MustAccAddressFromBech32(sendingValidatorAddress)
msg := banktypes.NewMsgSend(orgAddr, beneficiary, coins)
loggingContext := "sending " + denominator + " tokens"
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
}

View File

@ -2,6 +2,7 @@ package keeper
import ( import (
"context" "context"
"fmt"
config "github.com/planetmint/planetmint-go/config" config "github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/util" "github.com/planetmint/planetmint-go/util"
@ -50,6 +51,8 @@ func (k msgServer) AttestMachine(goCtx context.Context, msg *types.MsgAttestMach
} else { } else {
util.GetAppLogger().Info(ctx, "Machine NFT issuance successful: "+msg.Machine.String()) util.GetAppLogger().Info(ctx, "Machine NFT issuance successful: "+msg.Machine.String())
} }
k.sendInitialFundingTokensToMachine(goCtx, msg.GetMachine().GetAddress(), params)
} else { } else {
util.GetAppLogger().Info(ctx, "Not block proposer: skipping Machine NFT issuance") util.GetAppLogger().Info(ctx, "Not block proposer: skipping Machine NFT issuance")
} }
@ -60,9 +63,23 @@ func (k msgServer) AttestMachine(goCtx context.Context, msg *types.MsgAttestMach
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &types.MsgAttestMachineResponse{}, err return &types.MsgAttestMachineResponse{}, err
} }
func (k msgServer) sendInitialFundingTokensToMachine(goCtx context.Context, machineAddressString string, keeperParams types.Params) {
ctx := sdk.UnwrapSDKContext(goCtx)
machineAddress, err := sdk.AccAddressFromBech32(machineAddressString)
if err != nil {
util.GetAppLogger().Error(ctx, "error: for provided address "+machineAddress.String())
return
}
logMsg := fmt.Sprintf("transferring %v tokens to address %s", keeperParams.GetDaoMachineFundingAmount(), machineAddress.String())
util.GetAppLogger().Info(ctx, logMsg)
util.SendTokens(goCtx, machineAddress, keeperParams.GetDaoMachineFundingAmount(), keeperParams.GetDaoMachineFundingDenom())
}
func validateExtendedPublicKey(issuer string, cfg chaincfg.Params) bool { func validateExtendedPublicKey(issuer string, cfg chaincfg.Params) bool {
xpubKey, err := hdkeychain.NewKeyFromString(issuer) xpubKey, err := hdkeychain.NewKeyFromString(issuer)
if err != nil { if err != nil {

View File

@ -21,4 +21,6 @@ var (
ErrAssetRegistryReqFailure = errorsmod.Register(ModuleName, 13, "request to asset registry could not be created") ErrAssetRegistryReqFailure = errorsmod.Register(ModuleName, 13, "request to asset registry could not be created")
ErrAssetRegistryReqSending = errorsmod.Register(ModuleName, 14, "request to asset registry could not be sent") ErrAssetRegistryReqSending = errorsmod.Register(ModuleName, 14, "request to asset registry could not be sent")
ErrAssetRegistryRepsonse = errorsmod.Register(ModuleName, 15, "request response issue") ErrAssetRegistryRepsonse = errorsmod.Register(ModuleName, 15, "request response issue")
ErrInvalidAddress = errorsmod.Register(ModuleName, 16, "invalid address")
ErrTransferFailed = errorsmod.Register(ModuleName, 17, "transfer failed")
) )

View File

@ -13,17 +13,20 @@ func ParamKeyTable() paramtypes.KeyTable {
} }
// NewParams creates a new Params instance // NewParams creates a new Params instance
func NewParams(assetRegistryScheme string, assetRegistryDomain string, assetRegistryPath string) Params { func NewParams(assetRegistryScheme string, assetRegistryDomain string, assetRegistryPath string,
daoMachineFundingAmount uint64, daoMachineFundingDenom string) Params {
return Params{ return Params{
AssetRegistryScheme: assetRegistryScheme, AssetRegistryScheme: assetRegistryScheme,
AssetRegistryDomain: assetRegistryDomain, AssetRegistryDomain: assetRegistryDomain,
AssetRegistryPath: assetRegistryPath, AssetRegistryPath: assetRegistryPath,
DaoMachineFundingAmount: daoMachineFundingAmount,
DaoMachineFundingDenom: daoMachineFundingDenom,
} }
} }
// DefaultParams returns a default set of parameters // DefaultParams returns a default set of parameters
func DefaultParams() Params { func DefaultParams() Params {
return NewParams("https", "testnet-assets.rddl.io", "register_asset") return NewParams("https", "testnet-assets.rddl.io", "register_asset", 8800, "plmnt")
} }
// ParamSetPairs get the params.ParamSet // ParamSetPairs get the params.ParamSet

View File

@ -28,6 +28,8 @@ type Params struct {
AssetRegistryScheme string `protobuf:"bytes,1,opt,name=asset_registry_scheme,json=assetRegistryScheme,proto3" json:"asset_registry_scheme,omitempty"` AssetRegistryScheme string `protobuf:"bytes,1,opt,name=asset_registry_scheme,json=assetRegistryScheme,proto3" json:"asset_registry_scheme,omitempty"`
AssetRegistryDomain string `protobuf:"bytes,2,opt,name=asset_registry_domain,json=assetRegistryDomain,proto3" json:"asset_registry_domain,omitempty"` AssetRegistryDomain string `protobuf:"bytes,2,opt,name=asset_registry_domain,json=assetRegistryDomain,proto3" json:"asset_registry_domain,omitempty"`
AssetRegistryPath string `protobuf:"bytes,3,opt,name=asset_registry_path,json=assetRegistryPath,proto3" json:"asset_registry_path,omitempty"` AssetRegistryPath string `protobuf:"bytes,3,opt,name=asset_registry_path,json=assetRegistryPath,proto3" json:"asset_registry_path,omitempty"`
DaoMachineFundingAmount uint64 `protobuf:"varint,4,opt,name=dao_machine_funding_amount,json=daoMachineFundingAmount,proto3" json:"dao_machine_funding_amount,omitempty"`
DaoMachineFundingDenom string `protobuf:"bytes,5,opt,name=dao_machine_funding_denom,json=daoMachineFundingDenom,proto3" json:"dao_machine_funding_denom,omitempty"`
} }
func (m *Params) Reset() { *m = Params{} } func (m *Params) Reset() { *m = Params{} }
@ -83,6 +85,20 @@ func (m *Params) GetAssetRegistryPath() string {
return "" return ""
} }
func (m *Params) GetDaoMachineFundingAmount() uint64 {
if m != nil {
return m.DaoMachineFundingAmount
}
return 0
}
func (m *Params) GetDaoMachineFundingDenom() string {
if m != nil {
return m.DaoMachineFundingDenom
}
return ""
}
func init() { func init() {
proto.RegisterType((*Params)(nil), "planetmintgo.machine.Params") proto.RegisterType((*Params)(nil), "planetmintgo.machine.Params")
} }
@ -90,22 +106,26 @@ func init() {
func init() { proto.RegisterFile("planetmintgo/machine/params.proto", fileDescriptor_84cd778d65e6639c) } func init() { proto.RegisterFile("planetmintgo/machine/params.proto", fileDescriptor_84cd778d65e6639c) }
var fileDescriptor_84cd778d65e6639c = []byte{ var fileDescriptor_84cd778d65e6639c = []byte{
// 233 bytes of a gzipped FileDescriptorProto // 295 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2c, 0xc8, 0x49, 0xcc, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xb1, 0x4e, 0xeb, 0x30,
0x4b, 0x2d, 0xc9, 0xcd, 0xcc, 0x2b, 0x49, 0xcf, 0xd7, 0xcf, 0x4d, 0x4c, 0xce, 0xc8, 0xcc, 0x4b, 0x14, 0x40, 0xe3, 0xbe, 0xbc, 0x4a, 0x78, 0x23, 0x2d, 0x10, 0x3a, 0x98, 0xc2, 0xd4, 0x85, 0x44,
0xd5, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x41, 0xa2, 0x13, 0x30, 0x81, 0x2a, 0xb6, 0x4a, 0x55, 0xd8, 0x58, 0x22, 0x37, 0x31, 0x8e, 0x25, 0xec,
0x56, 0xa2, 0x07, 0x55, 0x22, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x56, 0xa0, 0x0f, 0x62, 0x41, 0x1b, 0xc5, 0x8e, 0x44, 0xff, 0x82, 0x91, 0x09, 0xf1, 0x39, 0x8c, 0x1d, 0x19, 0x51, 0xf2, 0x23,
0xd4, 0x2a, 0x2d, 0x63, 0xe4, 0x62, 0x0b, 0x00, 0x6b, 0x16, 0x32, 0xe2, 0x12, 0x4d, 0x2c, 0x2e, 0xa8, 0x4e, 0x04, 0x05, 0xb2, 0x5d, 0xe9, 0x9c, 0x23, 0xcb, 0xf7, 0xe2, 0xe3, 0xfc, 0x81, 0x2a,
0x4e, 0x2d, 0x89, 0x2f, 0x4a, 0x4d, 0xcf, 0x2c, 0x2e, 0x29, 0xaa, 0x8c, 0x2f, 0x4e, 0xce, 0x48, 0x66, 0xa4, 0x50, 0x86, 0x43, 0x28, 0x69, 0x92, 0x09, 0xc5, 0xc2, 0x9c, 0x16, 0x54, 0xea, 0x20,
0xcd, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x12, 0x06, 0x4b, 0x06, 0x41, 0xe5, 0x82, 0x2f, 0xc0, 0x80, 0x37, 0xdc, 0x56, 0x82, 0x56, 0x19, 0x0d, 0x39, 0x70, 0xb0, 0x42, 0xb8, 0x99,
0xc1, 0x52, 0x58, 0xf4, 0xa4, 0xe4, 0xe7, 0x26, 0x66, 0xe6, 0x49, 0x30, 0x61, 0xd1, 0xe3, 0x02, 0x1a, 0xf7, 0xe4, 0xa5, 0x87, 0xfb, 0x0b, 0x1b, 0x7b, 0x67, 0x78, 0x8f, 0x6a, 0xcd, 0x4c, 0x5c,
0x96, 0x12, 0xd2, 0xe3, 0x12, 0x46, 0xd3, 0x53, 0x90, 0x58, 0x92, 0x21, 0xc1, 0x0c, 0xd6, 0x21, 0x30, 0x2e, 0xb4, 0x29, 0x56, 0xb1, 0x4e, 0x32, 0x26, 0x99, 0x8f, 0xc6, 0x68, 0xb2, 0x13, 0x0d,
0x88, 0xa2, 0x23, 0x20, 0xb1, 0x24, 0xc3, 0x8a, 0x65, 0xc6, 0x02, 0x79, 0x06, 0x27, 0xdf, 0x13, 0x2c, 0x8c, 0x5a, 0x76, 0x6b, 0x51, 0x47, 0x93, 0x82, 0xa4, 0x42, 0xf9, 0xbd, 0x8e, 0x66, 0x66,
0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x91, 0x17, 0xe0, 0xc1, 0xaf, 0x26, 0xa7, 0x26, 0xf3, 0xff, 0xd9, 0x62, 0xf7, 0x47, 0xb1, 0xa0,
0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0x26, 0xf3, 0x2e, 0xf1, 0x28, 0xa5, 0x10, 0xb7, 0xff, 0x88, 0xef, 0x4b, 0x95, 0x0a, 0xc5, 0x63,
0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x47, 0xf8, 0x1c, 0x89, 0xa9, 0x9b, 0x9e, 0xaf, 0x5f, 0x01, 0x0f, 0x2a, 0xa1, 0x54, 0xc6, 0x77, 0xc7, 0x68, 0xe2, 0x46, 0x07, 0x29, 0x85, 0x79, 0x23, 0xdc, 0x34,
0xaa, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0xb0, 0xf7, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xfc, 0xca, 0x62, 0xef, 0x1c, 0x1f, 0x76, 0xc5, 0x29, 0x53, 0x20, 0xfd, 0xff, 0xf6, 0xc9, 0xfd,
0xff, 0x50, 0x39, 0xf4, 0xa3, 0x4f, 0x01, 0x00, 0x00, 0x3f, 0xed, 0x6c, 0x43, 0x2f, 0xdc, 0xe7, 0xd7, 0x23, 0xe7, 0x7a, 0xfe, 0x56, 0x11, 0xb4, 0xae,
0x08, 0xfa, 0xa8, 0x08, 0x7a, 0xaa, 0x89, 0xb3, 0xae, 0x89, 0xf3, 0x5e, 0x13, 0xe7, 0x6e, 0xca,
0x85, 0xc9, 0xca, 0x65, 0x90, 0x80, 0x0c, 0xbf, 0x37, 0xbe, 0x35, 0x9e, 0x72, 0x08, 0x1f, 0xbf,
0x4e, 0x64, 0x56, 0x39, 0xd3, 0xcb, 0xbe, 0x5d, 0xfb, 0xf4, 0x33, 0x00, 0x00, 0xff, 0xff, 0xb0,
0xd8, 0x7a, 0xbe, 0xc7, 0x01, 0x00, 0x00,
} }
func (m *Params) Marshal() (dAtA []byte, err error) { func (m *Params) Marshal() (dAtA []byte, err error) {
@ -128,6 +148,18 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.DaoMachineFundingDenom) > 0 {
i -= len(m.DaoMachineFundingDenom)
copy(dAtA[i:], m.DaoMachineFundingDenom)
i = encodeVarintParams(dAtA, i, uint64(len(m.DaoMachineFundingDenom)))
i--
dAtA[i] = 0x2a
}
if m.DaoMachineFundingAmount != 0 {
i = encodeVarintParams(dAtA, i, uint64(m.DaoMachineFundingAmount))
i--
dAtA[i] = 0x20
}
if len(m.AssetRegistryPath) > 0 { if len(m.AssetRegistryPath) > 0 {
i -= len(m.AssetRegistryPath) i -= len(m.AssetRegistryPath)
copy(dAtA[i:], m.AssetRegistryPath) copy(dAtA[i:], m.AssetRegistryPath)
@ -181,6 +213,13 @@ func (m *Params) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovParams(uint64(l)) n += 1 + l + sovParams(uint64(l))
} }
if m.DaoMachineFundingAmount != 0 {
n += 1 + sovParams(uint64(m.DaoMachineFundingAmount))
}
l = len(m.DaoMachineFundingDenom)
if l > 0 {
n += 1 + l + sovParams(uint64(l))
}
return n return n
} }
@ -315,6 +354,57 @@ func (m *Params) Unmarshal(dAtA []byte) error {
} }
m.AssetRegistryPath = string(dAtA[iNdEx:postIndex]) m.AssetRegistryPath = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DaoMachineFundingAmount", wireType)
}
m.DaoMachineFundingAmount = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowParams
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DaoMachineFundingAmount |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field DaoMachineFundingDenom", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowParams
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthParams
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthParams
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.DaoMachineFundingDenom = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipParams(dAtA[iNdEx:]) skippy, err := skipParams(dAtA[iNdEx:])