├── CODEOWNERS ├── x ├── developer │ ├── handler_test.go │ ├── manager │ │ ├── input │ │ │ ├── TestDeveloperManagerSuite │ │ │ │ ├── TestMoveIDA.input │ │ │ │ ├── TestPrivateAppIDAMove.input │ │ │ │ ├── TestUpdateAffiliated.input │ │ │ │ ├── TestMonthlyDistributeDevInflation │ │ │ │ │ ├── Success_no_developers.input │ │ │ │ │ ├── Fail_error_get_inflation_pool.input │ │ │ │ │ ├── Success_even_distribution.input │ │ │ │ │ ├── Fail_error_when_move_coin_to_account.input │ │ │ │ │ ├── Success_distribute_according_to_consumption.input │ │ │ │ │ └── Success_even_distribution_with_remainder.input │ │ │ │ ├── TestUpdateIDAAuth.input │ │ │ │ ├── TestGetDeveloper.input │ │ │ │ ├── TestBurnIDA.input │ │ │ │ ├── TestAppTransferIDA.input │ │ │ │ ├── TestRegisterDeveloper.input │ │ │ │ ├── TestUpdateDeveloper.input │ │ │ │ ├── TestGetLiveDeveloper │ │ │ │ │ └── All_developers.input │ │ │ │ ├── TestDoesDeveloperExist.input │ │ │ │ └── TestIssueIDA.input │ │ │ └── common │ │ │ │ ├── DeveloperBasic.input │ │ │ │ └── AffiliatedBasic.input │ │ └── golden │ │ │ └── TestDeveloperManagerSuite │ │ │ ├── TestMonthlyDistributeDevInflation │ │ │ ├── Succ_no_developers.golden │ │ │ ├── Fail_error_get_inflation_pool.golden │ │ │ ├── Success_even_distribution.golden │ │ │ ├── Fail_error_when_move_coin_to_account.golden │ │ │ ├── Success_even_distribution_with_remainder.golden │ │ │ └── Success_distribute_according_to_consumption.golden │ │ │ ├── TestInitGenesis │ │ │ ├── Fail_Invalid_Genesis_negative_reservePoolAmount.golden │ │ │ └── Success_Valid_Genesis.golden │ │ │ ├── TestReportConsumption │ │ │ ├── Success.golden │ │ │ └── Fail_developer_doesnt_exist.golden │ │ │ ├── TestGetDeveloper │ │ │ ├── Developer_exists.golden │ │ │ └── Developer_does_not_exist.golden │ │ │ ├── TestRegisterDeveloper │ │ │ ├── Fail_not_enough_stake.golden │ │ │ ├── Fail_Account_does_not_exist.golden │ │ │ ├── Fail_Account_has_user_role.golden │ │ │ ├── Fail_Account_is_not_a_Voter.golden │ │ │ ├── Fail_Developer_already_exists.golden │ │ │ ├── Fail_Error_from_paramHolder.golden │ │ │ ├── Fail_Account_is_not_a_Duty_Voter.golden │ │ │ ├── Fail_Error_from_vote.AssignDuty.golden │ │ │ ├── Fail_Error_from_vote.GetLinoStake.golden │ │ │ └── Success.golden │ │ │ ├── TestGetLiveDeveloper │ │ │ └── All_developers.golden │ │ │ ├── TestUpdateDeveloper │ │ │ ├── Fail_developer_deleted.golden │ │ │ ├── Fail_developer_doesnt_exist.golden │ │ │ └── Success.golden │ │ │ ├── TestDoesDeveloperExist │ │ │ ├── Developer_does_not_exist.golden │ │ │ ├── Developer_exist_deleted.golden │ │ │ └── Developer_exists_not_deleted.golden │ │ │ ├── TestIssueIDA │ │ │ ├── Fail_Developer_doesnt_exist.golden │ │ │ └── Fail_Developer_has_already_issued_IDA.golden │ │ │ └── TestUpdateAffiliated │ │ │ └── Success_deactivate.golden │ ├── types │ │ ├── query.go │ │ ├── keys.go │ │ └── codec.go │ └── model │ │ ├── dumper.go │ │ ├── developer.go │ │ └── load.json ├── vote │ ├── types │ │ ├── duty.go │ │ ├── events.go │ │ ├── keys.go │ │ └── codec.go │ ├── model │ │ ├── dumper.go │ │ ├── golden │ │ │ └── TestVoteStoreSuite │ │ │ │ ├── TestGetSetVoter.golden │ │ │ │ └── TestGetSetLinoStakeStats.golden │ │ ├── voter.go │ │ └── ir.go │ ├── manager │ │ ├── golden │ │ │ └── TestVoteManagerTestSuite │ │ │ │ ├── TestStakeIn │ │ │ │ ├── stake_in_with_insufficient_balance.golden │ │ │ │ ├── stake_in_amount_less_than_minimum_requirement.golden │ │ │ │ └── stake_in_minimum_requirement.golden │ │ │ │ ├── TestStakeInFor │ │ │ │ ├── stake_in_with_insufficient_balance.golden │ │ │ │ ├── stake_in_amount_less_than_minimum_requirement.golden │ │ │ │ └── stake_in_minimum_requirement.golden │ │ │ │ └── TestImportExport.golden │ │ └── mocks │ │ │ └── StakingHooks.go │ ├── client │ │ └── cli │ │ │ └── query.go │ └── querier.go ├── price │ ├── model │ │ ├── golden │ │ │ └── TestPriceStoreSuite │ │ │ │ ├── TestGetSetLastValidators.golden │ │ │ │ ├── TestGetSetCurrentPrice.golden │ │ │ │ ├── TestGetSetPriceHistory.golden │ │ │ │ ├── TestGetSetFedPrice.golden │ │ │ │ └── TestGetSetFeedHistory.golden │ │ ├── dumper.go │ │ └── wmprice.go │ ├── types │ │ ├── keys.go │ │ ├── codec.go │ │ ├── msg_test.go │ │ ├── errors.go │ │ └── msg.go │ ├── manager │ │ ├── input │ │ │ └── common │ │ │ │ └── genesis.input │ │ ├── utils.go │ │ └── golden │ │ │ └── TestPriceManagerSuite │ │ │ ├── TestFeedPrice │ │ │ ├── 3rd_time_rate_limited.golden │ │ │ └── succ_two_round.golden │ │ │ ├── TestInitGenesis.golden │ │ │ ├── TestUpdatePriceSlash │ │ │ ├── no_validator_feed_at_init_and_no_slash.golden │ │ │ └── testnet_no_slash.golden │ │ │ └── TestUpdatePriceCurrPrice │ │ │ └── initial_price_is_kept_no_feed.golden │ ├── handler.go │ ├── client │ │ └── cli │ │ │ ├── query.go │ │ │ └── tx.go │ ├── querier.go │ └── keeper.go ├── validator │ ├── types │ │ ├── keys.go │ │ └── codec.go │ ├── tick.go │ ├── manager │ │ └── hooks.go │ ├── model │ │ └── validator.go │ └── handler.go ├── global │ ├── manager │ │ ├── golden │ │ │ └── TestGlobalManagerSuite │ │ │ │ ├── TestGetPastDay.golden │ │ │ │ ├── TestInitGenesis.golden │ │ │ │ ├── TestEventErrIsolation.golden │ │ │ │ └── TestImportExport.golden │ │ └── fakeapp.go │ ├── model │ │ ├── golden │ │ │ └── TestGlobalStoreSuite │ │ │ │ ├── TestGetSetGlobalTime.golden │ │ │ │ ├── TestGetSetBCErrors.golden │ │ │ │ ├── TestGetSetEventErrors.golden │ │ │ │ └── TestGetSetDelTimeEventList.golden │ │ ├── global.go │ │ ├── ir.go │ │ └── dumper.go │ ├── types │ │ ├── keys.go │ │ └── errors.go │ ├── keeper.go │ └── client │ │ └── cli │ │ └── query.go ├── account │ ├── tick.go │ ├── model │ │ ├── golden │ │ │ └── TestAccountStoreSuite │ │ │ │ ├── TestMeta.golden │ │ │ │ ├── TestSupply.golden │ │ │ │ ├── TestPool.golden │ │ │ │ ├── TestBank.golden │ │ │ │ └── TestInfo.golden │ │ ├── dumper.go │ │ ├── account.go │ │ └── ir.go │ ├── types │ │ ├── codec.go │ │ └── keys.go │ └── manager │ │ └── event.go ├── post │ ├── types │ │ ├── keys.go │ │ ├── events.go │ │ └── codec.go │ ├── model │ │ ├── dumper.go │ │ ├── post.go │ │ └── ir.go │ ├── querier.go │ ├── client │ │ └── cli │ │ │ └── query.go │ └── keeper.go ├── reputation │ ├── tick.go │ ├── repv2 │ │ ├── state.go │ │ ├── types.go │ │ ├── const.go │ │ ├── utils.go │ │ ├── encodergen │ │ │ └── encodergen.py │ │ ├── encoder_test.go │ │ └── encoder.go │ ├── errors.go │ ├── keeper.go │ ├── client │ │ └── cli │ │ │ └── query.go │ └── querier.go ├── bandwidth │ ├── types │ │ ├── keys.go │ │ └── errors.go │ ├── tick.go │ ├── model │ │ ├── errors.go │ │ └── bandwidth.go │ └── keeper.go └── auth │ └── errors.go ├── client ├── types.go ├── broadcastcmd.go └── flags.go ├── .gitignore ├── types ├── dec.go ├── query.go ├── README.md ├── msg.go ├── pools.go ├── ida.go ├── dec_test.go ├── txencoder.go ├── event.go ├── minidollar.go ├── common_test.go └── error.go ├── CHANGELOG.md ├── app ├── errors.go └── version.go ├── scripts ├── update_genesis.sh ├── update_ubuntu.sh ├── install_cleveldb.sh ├── update_config.sh ├── bootstrap_ubuntu.sh └── install-golangci-lint.sh ├── .golangci.yml ├── docs ├── core │ ├── genesis.md │ ├── inflation.md │ ├── account.md │ ├── consensus.md │ ├── reputation.md │ ├── coinday.md │ ├── gov.md │ └── ecv.md ├── README.md └── changelog │ └── upgrade2-ida.md ├── CHANGELOG_PENDING.md ├── Dockerfile ├── param ├── keeper.go └── event.go ├── .travis.yml ├── .goreleaser.yml ├── test ├── post │ ├── publish_test.go │ └── donation_test.go └── account │ └── recover_test.go ├── utils ├── querier.go └── cli.go ├── testsuites └── ctx.go └── cmd └── README.md /CODEOWNERS: -------------------------------------------------------------------------------- 1 | @xiaoxiaff 2 | @WSmonkey 3 | @ZhimaoL 4 | -------------------------------------------------------------------------------- /x/developer/handler_test.go: -------------------------------------------------------------------------------- 1 | package developer 2 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMoveIDA.input: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestPrivateAppIDAMove.input: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestUpdateAffiliated.input: -------------------------------------------------------------------------------- 1 | [ 2 | ] 3 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Succ_no_developers.golden: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_no_developers.input: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestInitGenesis/Fail_Invalid_Genesis_negative_reservePoolAmount.golden: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /client/types.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/lino-network/lino/client/core" 5 | ) 6 | 7 | type OptionalSigner = core.OptionalSigner 8 | -------------------------------------------------------------------------------- /x/developer/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type QueryResultIDABalance struct { 4 | Amount string `json:"appida_amount"` 5 | Unauthed bool `json:"unauthed"` 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | vendor-new/ 3 | vendor/ 4 | cmd/lino/lino 5 | cmd/linocli/linocli 6 | server/server 7 | lino 8 | linocli 9 | bin/ 10 | dist/ 11 | *.key 12 | .idea 13 | -------------------------------------------------------------------------------- /x/vote/types/duty.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type VoterDuty int 4 | 5 | const ( 6 | DutyVoter VoterDuty = 0 7 | DutyApp VoterDuty = 1 8 | DutyValidator VoterDuty = 2 9 | DutyPending VoterDuty = 3 // pending is when voter is in unassign period 10 | ) 11 | -------------------------------------------------------------------------------- /x/price/model/golden/TestPriceStoreSuite/TestGetSetLastValidators.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "3", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/lastvals", 7 | "value": [ 8 | "user3", 9 | "user4" 10 | ] 11 | } 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /types/dec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // NewDecFromRat converting a / b to Dec, no float involved. 8 | func NewDecFromRat(a, b int64) sdk.Dec { 9 | decA := sdk.NewDec(a) 10 | decB := sdk.NewDec(b) 11 | return decA.Quo(decB) 12 | } 13 | -------------------------------------------------------------------------------- /x/price/model/golden/TestPriceStoreSuite/TestGetSetCurrentPrice.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/current", 7 | "value": { 8 | "price": "456", 9 | "update_at": "2000" 10 | } 11 | } 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /x/validator/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is module name 5 | ModuleName = "validator" 6 | 7 | // RouterKey is the message route for validator 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for validator 11 | QuerierRoute = ModuleName 12 | ) 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## version number 4 | --- 5 | 6 | *date* 7 | 8 | BREAKING CHANGES 9 | 10 | * [module] xxxxxx 11 | 12 | DEPRECATED 13 | 14 | * [module] xxxxxx 15 | 16 | FEATURES 17 | 18 | * [module] xxxxxx 19 | 20 | IMPROVEMENTS 21 | 22 | * [module] xxxxxx 23 | 24 | BUG FIXES 25 | 26 | * [module] xxxxxx -------------------------------------------------------------------------------- /x/vote/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | linotypes "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // UnassignDutyEvent - unassign duty needs a grace period and after that 8 | // duty and frozen money will be cleared. 9 | type UnassignDutyEvent struct { 10 | Username linotypes.AccountKey `json:"username"` 11 | } 12 | -------------------------------------------------------------------------------- /app/errors.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lino-network/lino/types" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | // Error constructors 12 | func ErrGenesisFailed(msg string) sdk.Error { 13 | return types.NewError(types.CodeGenesisFailed, fmt.Sprintf("genesis failed: %s", msg)) 14 | } 15 | -------------------------------------------------------------------------------- /x/validator/tick.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker - execute before every block. 9 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, vm ValidatorKeeper) { 10 | vm.OnBeginBlock(ctx, req) 11 | } 12 | -------------------------------------------------------------------------------- /x/global/manager/golden/TestGlobalManagerSuite/TestGetPastDay.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/time", 7 | "value": { 8 | "chain_start_time": "123456", 9 | "last_block_time": "123456", 10 | "past_minutes": "0" 11 | } 12 | } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /x/global/manager/golden/TestGlobalManagerSuite/TestInitGenesis.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/time", 7 | "value": { 8 | "chain_start_time": "123456", 9 | "last_block_time": "123456", 10 | "past_minutes": "0" 11 | } 12 | } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /x/global/model/golden/TestGlobalStoreSuite/TestGetSetGlobalTime.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/time", 7 | "value": { 8 | "chain_start_time": "123", 9 | "last_block_time": "234", 10 | "past_minutes": "999" 11 | } 12 | } 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestInitGenesis/Success_Valid_Genesis.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "3", 4 | "key": "", 5 | "val": { 6 | "type": "lino/reservepool", 7 | "value": { 8 | "total": { 9 | "amount": "1" 10 | }, 11 | "total_minidollar": "0" 12 | } 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /x/vote/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleKey is the name of the module 5 | ModuleName = "vote" 6 | 7 | // RouterKey is the message route for gov 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for gov 11 | QuerierRoute = ModuleName 12 | 13 | QueryVoter = "voter" 14 | QueryStakeStats = "stake-stats" 15 | ) 16 | -------------------------------------------------------------------------------- /x/global/model/global.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // GlobalTime - global time 8 | type GlobalTime struct { 9 | ChainStartTime int64 `json:"chain_start_time"` 10 | LastBlockTime int64 `json:"last_block_time"` 11 | PastMinutes int64 `json:"past_minutes"` 12 | } 13 | 14 | type EventError = types.EventError 15 | -------------------------------------------------------------------------------- /scripts/update_genesis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 3 ]; then 4 | echo "require 3 parameters: linux username, chainID, genesistime" 5 | exit 1 6 | fi 7 | 8 | USER=$1 9 | GENESIS=/home/$USER/.lino/config/genesis.json 10 | 11 | sed -i 's/^.*"chain_id": .*$/ "chain_id": "'"$2"'",/g' $GENESIS 12 | sed -i 's/^.*"genesis_time": .*$/ "genesis_time": "'"$3"'",/g' $GENESIS 13 | -------------------------------------------------------------------------------- /types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import sdk "github.com/cosmos/cosmos-sdk/types" 4 | 5 | func CheckPathContentAndMinLength(path []string, expectMinLength int) sdk.Error { 6 | if len(path) < expectMinLength { 7 | return ErrInvalidQueryPath() 8 | } 9 | for i := 0; i < expectMinLength; i++ { 10 | if path[i] == "" { 11 | return ErrInvalidQueryPath() 12 | } 13 | } 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /x/account/tick.go: -------------------------------------------------------------------------------- 1 | package account 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // EndBlocker - called every end blocker, udpate new round 9 | func EndBlocker(ctx sdk.Context, req abci.RequestEndBlock, am AccountKeeper) { 10 | err := am.Mint(ctx) 11 | if err != nil { 12 | panic(err) 13 | } 14 | return 15 | } 16 | -------------------------------------------------------------------------------- /x/post/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is module name 5 | ModuleName = "post" 6 | 7 | // RouterKey is the message route for post 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for post 11 | QuerierRoute = ModuleName 12 | 13 | // query stores 14 | QueryPostInfo = "info" 15 | QueryConsumptionWindow = "consumption-window" 16 | ) 17 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | deadline: 5m 3 | 4 | linters: 5 | enable-all: true 6 | disable: 7 | - gosimple 8 | - gocyclo 9 | - gochecknoinits 10 | - golint 11 | - gochecknoglobals 12 | - dupl 13 | - interfacer 14 | - gosec 15 | - unparam 16 | - lll 17 | - maligned 18 | - nakedret 19 | - scopelint 20 | - prealloc 21 | - varcheck 22 | - goconst 23 | -------------------------------------------------------------------------------- /x/global/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleKey is the name of the module 5 | ModuleName = "global" 6 | 7 | // QuerierRoute is the querier route for gov 8 | QuerierRoute = ModuleName 9 | 10 | QueryTimeEventList = "timeEventList" 11 | QueryGlobalTime = "globalTime" 12 | QueryGlobalEventErrors = "eventErrors" 13 | QueryGlobalBCEventErrors = "bcEventErrors" 14 | ) 15 | -------------------------------------------------------------------------------- /x/reputation/tick.go: -------------------------------------------------------------------------------- 1 | package reputation 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // EndBlocker - called every end blocker, udpate new round 9 | func EndBlocker(ctx sdk.Context, req abci.RequestEndBlock, rm ReputationKeeper) { 10 | err := rm.Update(ctx) 11 | if err != nil { 12 | panic(err) 13 | } 14 | return 15 | } 16 | -------------------------------------------------------------------------------- /x/price/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is module name 5 | ModuleName = "price" 6 | 7 | // RouterKey is the message route for post 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for post 11 | QuerierRoute = ModuleName 12 | 13 | // query stores 14 | QueryPriceCurrent = "current" 15 | QueryPriceHistory = "history" 16 | QueryLastFeed = "lastFeed" 17 | ) 18 | -------------------------------------------------------------------------------- /docs/core/genesis.md: -------------------------------------------------------------------------------- 1 | # Genesis 2 | 3 | Just like all other blockchain, Lino Blockchain also has genesis state when initialized. The genesis state in Lino Blockchain contains genesis account, genesis infra provider, genesis validator and genesis developer. The genesis validator is required to start the chain. 4 | 5 | ## Resource 6 | 7 | [Lino Testnet Genesis File](https://github.com/lino-network/testnets/blob/master/lino-testnet/genesis.json) -------------------------------------------------------------------------------- /x/price/model/golden/TestPriceStoreSuite/TestGetSetPriceHistory.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "456", 10 | "update_at": "2000" 11 | }, 12 | { 13 | "price": "789", 14 | "update_at": "3000" 15 | } 16 | ] 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /scripts/update_ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ### update golang to latest. 4 | sudo rm -rf /usr/local/go 5 | GOSOURCE=https://dl.google.com/go/go1.12.10.linux-amd64.tar.gz 6 | GOTARGET=/usr/local 7 | GOPATH=\$HOME/go 8 | PROFILE=/home/ubuntu/.profile 9 | 10 | curl -sSL $GOSOURCE -o /tmp/go.tar.gz 11 | sudo tar -xzf /tmp/go.tar.gz -C $GOTARGET 12 | sudo rm /tmp/go.tar.gz 13 | 14 | source $PROFILE 15 | sudo ldconfig 16 | go version 17 | -------------------------------------------------------------------------------- /CHANGELOG_PENDING.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.3.0 4 | --- 5 | 6 | Tue May 21 16:54:46 PDT 2019 7 | 8 | IMPROVEMENTS 9 | 10 | * [tendermint] upgrade to v0.31.5 (shall improve mempool performance and fix a leak issue) 11 | * [cosmos-sdk] upgrade to v0.34.4 12 | * [build] remove cleveldb related patches as tendermint/iavl are upgraded, cosmos's patch is required. 13 | * [build] remove cosmos clelveldb patch as they now support it through build tags. 14 | -------------------------------------------------------------------------------- /x/global/manager/fakeapp.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | //go:generate mockery -name FakeApp 4 | 5 | import ( 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | linotypes "github.com/lino-network/lino/types" 8 | ) 9 | 10 | type FakeApp interface { 11 | Hourly(ctx sdk.Context) []linotypes.BCEventErr 12 | Daily(ctx sdk.Context) []linotypes.BCEventErr 13 | Monthly(ctx sdk.Context) []linotypes.BCEventErr 14 | Yearly(ctx sdk.Context) []linotypes.BCEventErr 15 | } 16 | -------------------------------------------------------------------------------- /x/price/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec concrete types on wire codec 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(FeedPriceMsg{}, "lino/feedprice", nil) 10 | } 11 | 12 | // ModuleCdc is the module codec 13 | var ModuleCdc *codec.Codec 14 | 15 | func init() { 16 | ModuleCdc = codec.New() 17 | RegisterCodec(ModuleCdc) 18 | ModuleCdc.Seal() 19 | } 20 | -------------------------------------------------------------------------------- /x/vote/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | // sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | ) 8 | 9 | func NewVoteDumper(store VoteStorage) *testutils.Dumper { 10 | dumper := testutils.NewDumper(store.key, store.cdc) 11 | dumper.RegisterType(&Voter{}, "lino/voter", VoterSubstore) 12 | dumper.RegisterType(&LinoStakeStat{}, "lino/stakestats", LinoStakeStatSubStore) 13 | return dumper 14 | } 15 | -------------------------------------------------------------------------------- /x/account/model/golden/TestAccountStoreSuite/TestMeta.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "user1", 5 | "val": { 6 | "type": "lino/account/meta", 7 | "value": { 8 | "json_meta": "lol" 9 | } 10 | } 11 | }, 12 | { 13 | "prefix": "2", 14 | "key": "user2", 15 | "val": { 16 | "type": "lino/account/meta", 17 | "value": { 18 | "json_meta": "dota" 19 | } 20 | } 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /x/bandwidth/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName is module name 5 | ModuleName = "bandwidth" 6 | 7 | // RouterKey is the message route for bandwidth 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for bandwidth 11 | QuerierRoute = ModuleName 12 | 13 | // querier paths. 14 | QueryBandwidthInfo = "bandwidthinfo" 15 | QueryBlockInfo = "blockinfo" 16 | QueryAppBandwidthInfo = "appinfo" 17 | ) 18 | -------------------------------------------------------------------------------- /x/reputation/repv2/state.go: -------------------------------------------------------------------------------- 1 | package repv2 2 | 3 | // UserReputation - pk: Username 4 | type UserReputation struct { 5 | Username Uid `json:"username"` 6 | CustomerScore Rep `json:"customer_score"` 7 | FreeScore Rep `json:"free_score"` 8 | IsMiniDollar bool `json:"is_mini_dollar,omitempty"` 9 | } 10 | 11 | // UserReputationTable - pk by Username 12 | type UserReputationTable struct { 13 | Reputations []UserReputation `json:"reputations"` 14 | } 15 | -------------------------------------------------------------------------------- /x/account/model/golden/TestAccountStoreSuite/TestSupply.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "5", 4 | "key": "", 5 | "val": { 6 | "type": "lino/account/supply", 7 | "value": { 8 | "last_year_total": { 9 | "amount": "10000" 10 | }, 11 | "total": { 12 | "amount": "512354" 13 | }, 14 | "chain_start_time": "123", 15 | "last_inflation_time": "3245" 16 | } 17 | } 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestUpdateIDAAuth.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "4", 4 | "key": "testapp/testuser-affiliated", 5 | "val": { 6 | "type": "str", 7 | "value": "t" 8 | } 9 | }, 10 | { 11 | "prefix": "5", 12 | "key": "testuser-affiliated", 13 | "val": { 14 | "type": "lino/role", 15 | "value": { 16 | "aa": "testapp" 17 | } 18 | } 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /x/post/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | // sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | "github.com/lino-network/lino/types" 8 | ) 9 | 10 | func NewPostDumper(store PostStorage) *testutils.Dumper { 11 | dumper := testutils.NewDumper(store.key, store.cdc) 12 | dumper.RegisterType(&Post{}, "lino/post", PostSubStore) 13 | dumper.RegisterType(&types.MiniDollar{}, "lino/minidollar", ConsumptionWindowSubStore) 14 | return dumper 15 | } 16 | -------------------------------------------------------------------------------- /types/README.md: -------------------------------------------------------------------------------- 1 | # Lino Blockchain Types 2 | 3 | This directory is used to define all models in our internal blockchain storage. For example we need to define *account* and *post* here. 4 | 5 | For example, in *account* model, we need to define all account KVStore models and provide a middleware to interact with all models related operation. 6 | 7 | 8 | [Design Doc](https://docs.google.com/document/d/1Ytd57axPfJ13TSGVU_Yykv8ijW_VuWtx1s79ny6i5M8). 9 | [Cosmos Example](https://github.com/cosmos/cosmos-sdk/tree/develop/examples/basecoin). -------------------------------------------------------------------------------- /x/developer/manager/input/common/DeveloperBasic.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/price/manager/input/common/genesis.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "1200", 10 | "update_at": "0" 11 | } 12 | ] 13 | } 14 | }, 15 | { 16 | "prefix": "2", 17 | "key": "", 18 | "val": { 19 | "type": "lino/price/current", 20 | "value": { 21 | "price": "1200", 22 | "update_at": "0" 23 | } 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /app/version.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | // "github.com/spf13/viper" 8 | ) 9 | 10 | var Version = "" 11 | 12 | // VersionCmd - print current version of binary. 13 | func VersionCmd() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "version", 16 | Short: "version prints the version of this binary", 17 | Args: cobra.NoArgs, 18 | RunE: func(_ *cobra.Command, _ []string) error { 19 | fmt.Println(Version) 20 | return nil 21 | }, 22 | } 23 | 24 | return cmd 25 | } 26 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestGetDeveloper.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestReportConsumption/Success.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "10", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestBurnIDA.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "3", 4 | "key": "", 5 | "val": { 6 | "type": "lino/reservepool", 7 | "value": { 8 | "total": { 9 | "amount": "10" 10 | }, 11 | "total_minidollar": "1000" 12 | } 13 | } 14 | }, 15 | { 16 | "prefix": "6", 17 | "key": "testapp", 18 | "val": { 19 | "type": "lino/appidastats", 20 | "value": { 21 | "total": "1000" 22 | } 23 | } 24 | } 25 | ] 26 | -------------------------------------------------------------------------------- /x/vote/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // Register concrete types on wire codec 8 | func RegisterWire(cdc *wire.Codec) { 9 | cdc.RegisterConcrete(StakeInMsg{}, "lino/stakeIn", nil) 10 | cdc.RegisterConcrete(StakeOutMsg{}, "lino/stakeOut", nil) 11 | cdc.RegisterConcrete(ClaimInterestMsg{}, "lino/claimInterest", nil) 12 | cdc.RegisterConcrete(StakeInForMsg{}, "lino/stakeInFor", nil) 13 | } 14 | 15 | var msgCdc = wire.New() 16 | 17 | func init() { 18 | RegisterWire(msgCdc) 19 | } 20 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestGetDeveloper/Developer_exists.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestGetDeveloper/Developer_does_not_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestReportConsumption/Fail_developer_doesnt_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/global/model/golden/TestGlobalStoreSuite/TestGetSetBCErrors.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "3", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/bceventerr", 7 | "value": [ 8 | { 9 | "time": "123", 10 | "err_code": 123, 11 | "err_code_space": "̕", 12 | "reason": "inflation failed" 13 | }, 14 | { 15 | "time": "456", 16 | "err_code": 34, 17 | "err_code_space": "ر", 18 | "reason": "validator failed" 19 | } 20 | ] 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /x/post/model/post.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // Post - post is created by the CreatedBy. 8 | type Post struct { 9 | PostID string `json:"post_id"` 10 | Title string `json:"title"` 11 | Content string `json:"content"` 12 | Author types.AccountKey `json:"author"` 13 | CreatedBy types.AccountKey `json:"created_by"` 14 | CreatedAt int64 `json:"created_at"` 15 | UpdatedAt int64 `json:"updated_at"` 16 | IsDeleted bool `json:"is_deleted"` 17 | } 18 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Fail_error_get_inflation_pool.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Fail_error_get_inflation_pool.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeIn/stake_in_with_insufficient_balance.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "0", 5 | "val": { 6 | "type": "lino/stakestats", 7 | "value": { 8 | "total_consumption_friction": { 9 | "amount": "0" 10 | }, 11 | "unclaimed_friction": { 12 | "amount": "0" 13 | }, 14 | "total_lino_power": { 15 | "amount": "0" 16 | }, 17 | "unclaimed_lino_power": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeInFor/stake_in_with_insufficient_balance.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "0", 5 | "val": { 6 | "type": "lino/stakestats", 7 | "value": { 8 | "total_consumption_friction": { 9 | "amount": "0" 10 | }, 11 | "unclaimed_friction": { 12 | "amount": "0" 13 | }, 14 | "total_lino_power": { 15 | "amount": "0" 16 | }, 17 | "unclaimed_lino_power": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // nolint 4 | import ( 5 | wire "github.com/cosmos/cosmos-sdk/codec" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // Transactions messages must fulfill the Msg 10 | type Msg interface { 11 | sdk.Msg 12 | GetPermission() Permission 13 | GetConsumeAmount() Coin 14 | } 15 | 16 | type AddrMsg interface { 17 | sdk.Msg 18 | GetAccOrAddrSigners() []AccOrAddr 19 | } 20 | 21 | // Register the lino message type 22 | func RegisterWire(cdc *wire.Codec) { 23 | cdc.RegisterInterface((*Msg)(nil), nil) 24 | cdc.RegisterInterface((*AddrMsg)(nil), nil) 25 | } 26 | -------------------------------------------------------------------------------- /x/price/model/golden/TestPriceStoreSuite/TestGetSetFedPrice.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "user1", 5 | "val": { 6 | "type": "lino/price/fedprice", 7 | "value": { 8 | "validator": "user1", 9 | "price": "123", 10 | "update_at": "1000" 11 | } 12 | } 13 | }, 14 | { 15 | "prefix": "0", 16 | "key": "user2", 17 | "val": { 18 | "type": "lino/price/fedprice", 19 | "value": { 20 | "validator": "user2", 21 | "price": "456", 22 | "update_at": "2000" 23 | } 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeIn/stake_in_amount_less_than_minimum_requirement.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "0", 5 | "val": { 6 | "type": "lino/stakestats", 7 | "value": { 8 | "total_consumption_friction": { 9 | "amount": "0" 10 | }, 11 | "unclaimed_friction": { 12 | "amount": "0" 13 | }, 14 | "total_lino_power": { 15 | "amount": "0" 16 | }, 17 | "unclaimed_lino_power": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /x/post/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | linotypes "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // RewardEvent - when donation occurred, a reward event will be register 8 | // at 7 days later. After 7 days reward event will be executed and send 9 | // inflation to author. 10 | type RewardEvent struct { 11 | PostAuthor linotypes.AccountKey `json:"post_author"` 12 | PostID string `json:"post_id"` 13 | Consumer linotypes.AccountKey `json:"consumer"` 14 | Evaluate linotypes.MiniDollar `json:"evaluate"` 15 | FromApp linotypes.AccountKey `json:"from_app"` 16 | } 17 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeInFor/stake_in_amount_less_than_minimum_requirement.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "0", 5 | "val": { 6 | "type": "lino/stakestats", 7 | "value": { 8 | "total_consumption_friction": { 9 | "amount": "0" 10 | }, 11 | "unclaimed_friction": { 12 | "amount": "0" 13 | }, 14 | "total_lino_power": { 15 | "amount": "0" 16 | }, 17 | "unclaimed_lino_power": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /x/developer/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleKey is the name of the module 5 | ModuleName = "developer" 6 | 7 | // RouterKey is the message route for developer 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for developer 11 | QuerierRoute = ModuleName 12 | 13 | // Query sub spaces. 14 | QueryDeveloper = "dev" 15 | QueryDeveloperList = "devList" 16 | QueryIDA = "devIDA" 17 | QueryIDABalance = "devIDABalance" 18 | QueryAffiliated = "devAffiliated" 19 | QueryReservePool = "devReservePool" 20 | QueryIDAStats = "devIDAStats" 21 | ) 22 | -------------------------------------------------------------------------------- /scripts/install_cleveldb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # install snappy & cleveldb 4 | sudo apt-get update 5 | sudo apt-get install -y build-essential gcc g++ make 6 | 7 | sudo apt-get install -y libsnappy-dev 8 | homedir="$PWD" 9 | 10 | wget https://github.com/google/leveldb/archive/v1.20.tar.gz && \ 11 | tar -zxvf v1.20.tar.gz && \ 12 | cd leveldb-1.20/ && \ 13 | make && \ 14 | sudo cp -r out-static/lib* out-shared/lib* /usr/local/lib/ && \ 15 | cd include/ && \ 16 | sudo cp -r leveldb /usr/local/include/ && \ 17 | sudo ldconfig 18 | 19 | cd "$homedir" 20 | 21 | rm -f v1.20.tar.gz 22 | rm -rf leveldb-1.20 23 | -------------------------------------------------------------------------------- /x/reputation/repv2/types.go: -------------------------------------------------------------------------------- 1 | package repv2 2 | 3 | type Uid string 4 | type Pid string 5 | 6 | // Time in this package is an int64, unix timestamp, in seconds. 7 | type Time int64 8 | 9 | type bigInt = Int 10 | 11 | type LinoCoin = bigInt 12 | type IF = bigInt // Impact factor 13 | type Rep = bigInt 14 | 15 | type RoundId int64 16 | 17 | // used in topN. 18 | type PostIFPair struct { 19 | Pid Pid `json:"p"` 20 | SumIF IF `json:"s_if"` 21 | } 22 | 23 | // merged donation, used in userUnsettled. 24 | type Donation struct { 25 | Pid Pid `json:"p"` 26 | Amount LinoCoin `json:"a"` 27 | Impact IF `json:"i"` 28 | } 29 | -------------------------------------------------------------------------------- /x/reputation/repv2/const.go: -------------------------------------------------------------------------------- 1 | package repv2 2 | 3 | const ( 4 | // Inherited from testnet, the unit of 1 reputation is one coin 5 | // of testnet, which is 10^(-5) * 0.012 USD. 6 | // Caller need to convert the amount of donation to the number of test coins. 7 | DefaultRoundDurationSeconds = 25 * 3600 // how many seconds does a round last, default: 25 hours 8 | DefaultSampleWindowSize = 10 // how many rounds are used to sample out user's customer score. 9 | DefaultDecayFactor = 10 // reputation decay factor %. 10 | 11 | // Initial and minimum score is 10^(-5), one coin. 12 | DefaultInitialReputation = 1 13 | ) 14 | -------------------------------------------------------------------------------- /x/reputation/repv2/utils.go: -------------------------------------------------------------------------------- 1 | package repv2 2 | 3 | // PrefixEndBytes returns the []byte that would end a 4 | // range query for all []byte with a certain prefix 5 | // Deals with last byte of prefix being FF without overflowing 6 | func PrefixEndBytes(prefix []byte) []byte { 7 | if len(prefix) == 0 { 8 | return nil 9 | } 10 | 11 | end := make([]byte, len(prefix)) 12 | copy(end, prefix) 13 | 14 | for { 15 | if end[len(end)-1] != byte(255) { 16 | end[len(end)-1]++ 17 | break 18 | } else { 19 | end = end[:len(end)-1] 20 | if len(end) == 0 { 21 | end = nil 22 | break 23 | } 24 | } 25 | } 26 | return end 27 | } 28 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestAppTransferIDA.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "testapp/testapp", 5 | "val": { 6 | "type": "lino/bank", 7 | "value": { 8 | "b": "10000" 9 | } 10 | } 11 | }, 12 | { 13 | "prefix": "5", 14 | "key": "testapp-affiliated", 15 | "val": { 16 | "type": "lino/role", 17 | "value": { 18 | "aa": "testapp" 19 | } 20 | } 21 | }, 22 | { 23 | "prefix": "4", 24 | "key": "testapp/testapp-affiliated", 25 | "val": { 26 | "type": "str", 27 | "value": "t" 28 | } 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /x/price/manager/utils.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // price: 1 coin = ? minidollar 8 | func coinToMiniDollar(coin types.Coin, price types.MiniDollar) (bought types.MiniDollar) { 9 | return price.Multiply(types.NewMiniDollarFromInt(coin.Amount)) 10 | } 11 | 12 | // convert minidollar to coin 13 | // price: 1 coin = ? minidollar. 14 | func miniDollarToCoin(dollar types.MiniDollar, price types.MiniDollar) (bought types.Coin, used types.MiniDollar) { 15 | c := dollar.Quo(price.Int) 16 | bought = types.NewCoin(c) 17 | used = types.NewMiniDollarFromInt(c.Mul(price.Int)) 18 | return 19 | } 20 | -------------------------------------------------------------------------------- /x/account/model/golden/TestAccountStoreSuite/TestPool.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "4", 4 | "key": "inflation/developer", 5 | "val": { 6 | "type": "lino/account/pool", 7 | "value": { 8 | "name": "inflation/developer", 9 | "balance": { 10 | "amount": "45567" 11 | } 12 | } 13 | } 14 | }, 15 | { 16 | "prefix": "4", 17 | "key": "inflation/validator", 18 | "val": { 19 | "type": "lino/account/pool", 20 | "value": { 21 | "name": "inflation/validator", 22 | "balance": { 23 | "amount": "1234" 24 | } 25 | } 26 | } 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /x/post/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec concrete types on wire codec 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(CreatePostMsg{}, "lino/createPost", nil) 10 | cdc.RegisterConcrete(UpdatePostMsg{}, "lino/updatePost", nil) 11 | cdc.RegisterConcrete(DeletePostMsg{}, "lino/deletePost", nil) 12 | cdc.RegisterConcrete(DonateMsg{}, "lino/donate", nil) 13 | cdc.RegisterConcrete(IDADonateMsg{}, "lino/idaDonate", nil) 14 | } 15 | 16 | // ModuleCdc is the module codec 17 | var ModuleCdc *codec.Codec 18 | 19 | func init() { 20 | ModuleCdc = codec.New() 21 | RegisterCodec(ModuleCdc) 22 | ModuleCdc.Seal() 23 | } 24 | -------------------------------------------------------------------------------- /scripts/update_config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$#" -ne 3 ]; then 4 | echo "require 3 parameters: linux username, persistent_peers, private_peer_ids" 5 | exit 1 6 | fi 7 | 8 | USER=$1 9 | CONFIG=/home/$USER/.lino/config/config.toml 10 | 11 | sed -i 's/^db_backend = "leveldb"$/db_backend = "cleveldb"/g' $CONFIG 12 | 13 | sed -i 's/^persistent_peers = ""$/persistent_peers = "'"$2"'"/g' $CONFIG 14 | 15 | sed -i 's/^send_rate = 5120000$/send_rate = 128000000/g' $CONFIG 16 | 17 | sed -i 's/^recv_rate = 5120000$/recv_rate = 128000000/g' $CONFIG 18 | 19 | sed -i 's/^private_peer_ids = ""$/private_peer_ids = "'"$3"'"/g' $CONFIG 20 | 21 | sed -i 's/^timeout_commit = "5s"$/timeout_commit = "3s"/g' $CONFIG 22 | -------------------------------------------------------------------------------- /x/account/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | // sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | ) 8 | 9 | func NewAccountDumper(store AccountStorage) *testutils.Dumper { 10 | dumper := testutils.NewDumper(store.key, store.cdc) 11 | dumper.RegisterType(&AccountInfo{}, "lino/account/info", AccountInfoSubstore) 12 | dumper.RegisterType(&AccountBank{}, "lino/account/bank", AccountBankSubstore) 13 | dumper.RegisterType(&AccountMeta{}, "lino/account/meta", AccountMetaSubstore) 14 | dumper.RegisterType(&Pool{}, "lino/account/pool", AccountPoolSubstore) 15 | dumper.RegisterType(&Supply{}, "lino/account/supply", AccountSupplySubstore) 16 | return dumper 17 | } 18 | -------------------------------------------------------------------------------- /x/bandwidth/tick.go: -------------------------------------------------------------------------------- 1 | package bandwidth 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | abci "github.com/tendermint/tendermint/abci/types" 6 | ) 7 | 8 | // BeginBlocker 9 | func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, bm BandwidthKeeper) { 10 | if ctx.BlockHeight() == 1 { 11 | err := bm.ReCalculateAppBandwidthInfo(ctx) 12 | if err != nil { 13 | panic(err) 14 | } 15 | } 16 | if err := bm.BeginBlocker(ctx); err != nil { 17 | panic(err) 18 | } 19 | return 20 | } 21 | 22 | // EndBlocker 23 | func EndBlocker( 24 | ctx sdk.Context, req abci.RequestEndBlock, bm BandwidthKeeper) { 25 | if err := bm.EndBlocker(ctx); err != nil { 26 | panic(err) 27 | } 28 | return 29 | } 30 | -------------------------------------------------------------------------------- /x/validator/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // RegisterCodec concrete types on wire codec 8 | func RegisterCodec(cdc *codec.Codec) { 9 | cdc.RegisterConcrete(ValidatorRegisterMsg{}, "lino/valRegister", nil) 10 | cdc.RegisterConcrete(ValidatorRevokeMsg{}, "lino/valRevoke", nil) 11 | cdc.RegisterConcrete(VoteValidatorMsg{}, "lino/voteValidator", nil) 12 | cdc.RegisterConcrete(ValidatorUpdateMsg{}, "lino/valUpdate", nil) 13 | } 14 | 15 | // ModuleCdc is the module codec 16 | var ModuleCdc *codec.Codec 17 | 18 | func init() { 19 | ModuleCdc = codec.New() 20 | RegisterCodec(ModuleCdc) 21 | codec.RegisterCrypto(ModuleCdc) 22 | ModuleCdc.Seal() 23 | } 24 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestRegisterDeveloper.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/global/model/golden/TestGlobalStoreSuite/TestGetSetEventErrors.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/eventerr", 7 | "value": [ 8 | { 9 | "time": "123", 10 | "event": { 11 | "type": "lino/testevent", 12 | "value": { 13 | "name": "lol" 14 | } 15 | }, 16 | "err_code": 123 17 | }, 18 | { 19 | "time": "456", 20 | "event": { 21 | "type": "lino/testevent", 22 | "value": { 23 | "name": "dota" 24 | } 25 | }, 26 | "err_code": 999 27 | } 28 | ] 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /docs/core/inflation.md: -------------------------------------------------------------------------------- 1 | # Inflation Distribution 2 | 3 | infra provider inflation pool and content creator inflation pool. The inflation pool will be calculated annually and the total inflation highest cap is 9.8% and lowest cap is 3.0% of annually consumption increment. The first two years since the blockchain doesn’t have increment data it goes for 9.8%. 4 | 5 | Validators produce blocks for blockchain and keep blockchain running. As the reward the blockchain will distribute inflation evenly to all oncall validators hourly. App developer and infra provider get inflation monthly based on their contribution. The content creator inflation pool will be charged hourly. The donation friction get content bonus from content creator inflation pool after 7 days window. 6 | -------------------------------------------------------------------------------- /scripts/bootstrap_ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ### install golang 4 | 5 | GOSOURCE=https://dl.google.com/go/go1.12.10.linux-amd64.tar.gz 6 | GOTARGET=/usr/local 7 | GOPATH=\$HOME/go 8 | PROFILE=/home/ubuntu/.profile 9 | 10 | curl -sSL $GOSOURCE -o /tmp/go.tar.gz 11 | sudo tar -xzf /tmp/go.tar.gz -C $GOTARGET 12 | sudo rm /tmp/go.tar.gz 13 | 14 | # apply environment configuration to the user's .profile 15 | touch $PROFILE 16 | printf "\n" >> $PROFILE 17 | printf "# golang configuration\n" >> $PROFILE 18 | printf "export GOROOT=$GOTARGET/go\n" >> $PROFILE 19 | printf "export GOPATH=$GOPATH\n" >> $PROFILE 20 | printf "export PATH=\$PATH:$GOTARGET/go/bin:$GOPATH/bin\n" >> $PROFILE 21 | 22 | source $PROFILE 23 | sudo ldconfig 24 | go version 25 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_not_enough_stake.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Account_does_not_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Account_has_user_role.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Account_is_not_a_Voter.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Developer_already_exists.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Error_from_paramHolder.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Account_is_not_a_Duty_Voter.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Error_from_vote.AssignDuty.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Fail_Error_from_vote.GetLinoStake.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "5", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/role", 26 | "value": { 27 | "aa": "test2" 28 | } 29 | } 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /x/account/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | ) 7 | 8 | // RegisterWire - register concrete types on wire codec 9 | func RegisterWire(cdc *wire.Codec) { 10 | cdc.RegisterConcrete(RegisterV2Msg{}, "lino/registerv2", nil) 11 | cdc.RegisterConcrete(TransferMsg{}, "lino/transfer", nil) 12 | cdc.RegisterConcrete(TransferV2Msg{}, "lino/transferv2", nil) 13 | cdc.RegisterConcrete(RecoverMsg{}, "lino/recover", nil) 14 | cdc.RegisterConcrete(UpdateAccountMsg{}, "lino/updateAcc", nil) 15 | } 16 | 17 | var msgCdc = wire.New() 18 | 19 | func init() { 20 | RegisterWire(msgCdc) 21 | sdk.RegisterCodec(msgCdc) 22 | wire.RegisterCrypto(msgCdc) 23 | msgCdc.Seal() 24 | } 25 | -------------------------------------------------------------------------------- /x/global/manager/golden/TestGlobalManagerSuite/TestEventErrIsolation.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/global/time", 7 | "value": { 8 | "chain_start_time": "123456", 9 | "last_block_time": "123456", 10 | "past_minutes": "0" 11 | } 12 | } 13 | }, 14 | { 15 | "prefix": "2", 16 | "key": "", 17 | "val": { 18 | "type": "lino/global/eventerr", 19 | "value": [ 20 | { 21 | "time": "123486", 22 | "event": { 23 | "type": "lino/testevent", 24 | "value": { 25 | "id": "0" 26 | } 27 | }, 28 | "err_code": 100000 29 | } 30 | ] 31 | } 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /scripts/install-golangci-lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | f_sha256() { 6 | local l_file 7 | l_file=$1 8 | python -sBc "import hashlib;print(hashlib.sha256(open('$l_file','rb').read()).hexdigest())" 9 | } 10 | 11 | installer="$(mktemp)" 12 | trap "rm -f ${installer}" EXIT 13 | 14 | GOBIN="${1}" 15 | VERSION="${2}" 16 | HASHSUM="${3}" 17 | CURL="$(which curl)" 18 | 19 | echo "Downloading golangci-lint ${VERSION} installer ..." >&2 20 | "${CURL}" -sfL "https://raw.githubusercontent.com/golangci/golangci-lint/${VERSION}/install.sh" > "${installer}" 21 | 22 | echo "Checking hashsum ..." >&2 23 | [ "${HASHSUM}" = "$(f_sha256 ${installer})" ] 24 | chmod +x "${installer}" 25 | 26 | echo "Launching installer ..." >&2 27 | exec "${installer}" -d -b "${GOBIN}" "${VERSION}" 28 | -------------------------------------------------------------------------------- /x/account/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleKey is the name of the module 5 | ModuleName = "account" 6 | 7 | // RouterKey is the message route for account 8 | RouterKey = ModuleName 9 | 10 | // QuerierRoute is the querier route for account 11 | QuerierRoute = ModuleName 12 | 13 | // query pathes 14 | QueryAccountInfo = "info" 15 | QueryAccountBank = "bank" 16 | QueryAccountBankByAddress = "bankByAddress" 17 | QueryAccountMeta = "meta" 18 | QueryAccountPendingCoinDay = "pendingCoinDay" 19 | QueryAccountGrantPubKeys = "grantPubKey" 20 | QueryAccountAllGrantPubKeys = "allGrantPubKey" 21 | QueryTxAndAccountSequence = "txAndSeq" 22 | QueryPool = "pool" 23 | QuerySupply = "supply" 24 | ) 25 | -------------------------------------------------------------------------------- /x/price/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | // sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | linotypes "github.com/lino-network/lino/types" 8 | ) 9 | 10 | func NewPriceDumper(store PriceStorage) *testutils.Dumper { 11 | dumper := testutils.NewDumper(store.key, store.cdc) 12 | dumper.RegisterType(&FedPrice{}, "lino/price/fedprice", fedPriceSubStore) 13 | dumper.RegisterType(&[]TimePrice{}, "lino/price/history", priceHistorySubStore) 14 | dumper.RegisterType(&TimePrice{}, "lino/price/current", currentPriceSubStore) 15 | dumper.RegisterType(&[]linotypes.AccountKey{}, "lino/price/lastvals", lastValidatorsSubStore) 16 | dumper.RegisterType(&[]FeedHistory{}, "lino/price/feedhistory", feedHistorySubStore) 17 | return dumper 18 | } 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.12 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y make tar sudo wget curl 5 | 6 | RUN mkdir -p src/github.com/lino-network/lino 7 | WORKDIR src/github.com/lino-network/lino 8 | 9 | COPY . . 10 | RUN make get_tools 11 | RUN make install 12 | 13 | RUN lino init 14 | COPY genesis/upgrade5/config.toml /root/.lino/config/config.toml 15 | COPY genesis/upgrade5/genesis.json /root/.lino/config/genesis.json 16 | RUN cd /root/.lino && wget https://lino-blockchain-opendata.s3.amazonaws.com/prd/prevstates.tar.gz 17 | RUN cd /root/.lino && tar -xf prevstates.tar.gz 18 | 19 | # prometheus if enabled 20 | EXPOSE 26660 21 | # p2p 22 | EXPOSE 26656 23 | # tendermint rpc 24 | EXPOSE 26657 25 | # abci app 26 | EXPOSE 26658 27 | 28 | CMD ["lino", "unsafe-reset-all"] 29 | CMD ["lino", "start"] 30 | -------------------------------------------------------------------------------- /x/post/model/ir.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // PostIR - is the IR of Post. 8 | type PostIR struct { 9 | PostID string `json:"post_id"` 10 | Title string `json:"title"` 11 | Content string `json:"content"` 12 | Author types.AccountKey `json:"author"` 13 | CreatedBy types.AccountKey `json:"created_by"` 14 | CreatedAt int64 `json:"created_at"` 15 | UpdatedAt int64 `json:"updated_at"` 16 | IsDeleted bool `json:"is_deleted"` 17 | } 18 | 19 | // PostTablesIR - is the Post State. 20 | type PostTablesIR struct { 21 | Version int `json:"version"` 22 | Posts []PostIR `json:"posts"` 23 | ConsumptionWindow types.MiniDollar `json:"consumption_window"` 24 | } 25 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestFeedPrice/3rd_time_rate_limited.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "val2", 5 | "val": { 6 | "type": "lino/price/fedprice", 7 | "value": { 8 | "validator": "val2", 9 | "price": "200", 10 | "update_at": "600" 11 | } 12 | } 13 | }, 14 | { 15 | "prefix": "1", 16 | "key": "", 17 | "val": { 18 | "type": "lino/price/history", 19 | "value": [ 20 | { 21 | "price": "1200", 22 | "update_at": "0" 23 | } 24 | ] 25 | } 26 | }, 27 | { 28 | "prefix": "2", 29 | "key": "", 30 | "val": { 31 | "type": "lino/price/current", 32 | "value": { 33 | "price": "1200", 34 | "update_at": "0" 35 | } 36 | } 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestInitGenesis.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "1234", 10 | "update_at": "0" 11 | } 12 | ] 13 | } 14 | }, 15 | { 16 | "prefix": "2", 17 | "key": "", 18 | "val": { 19 | "type": "lino/price/current", 20 | "value": { 21 | "price": "1234", 22 | "update_at": "0" 23 | } 24 | } 25 | }, 26 | { 27 | "prefix": "4", 28 | "key": "", 29 | "val": { 30 | "type": "lino/price/feedhistory", 31 | "value": [ 32 | { 33 | "price": "1234", 34 | "feeded": null, 35 | "update_at": "0" 36 | } 37 | ] 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/reputation/errors.go: -------------------------------------------------------------------------------- 1 | package reputation 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/lino-network/lino/types" 8 | ) 9 | 10 | // ErrAccountNotFound - error when account is not found 11 | func ErrAccountNotFound(author types.AccountKey) sdk.Error { 12 | return types.NewError(types.CodeAccountNotFound, fmt.Sprintf("account %v is not found", author)) 13 | } 14 | 15 | // ErrPostNotFound - error when post is not found 16 | func ErrPostNotFound(permlink types.Permlink) sdk.Error { 17 | return types.NewError(types.CodePostNotFound, fmt.Sprintf("post %v doesn't exist", permlink)) 18 | } 19 | 20 | // ErrQueryFailed - error when query reputation store failed 21 | func ErrQueryFailed() sdk.Error { 22 | return types.NewError(types.CodeReputationQueryFailed, fmt.Sprintf("query reputation store failed")) 23 | } 24 | -------------------------------------------------------------------------------- /x/bandwidth/model/errors.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lino-network/lino/types" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | // ErrBandwidthInfoNotFound - error if bandwidth info is not found 12 | func ErrBandwidthInfoNotFound() sdk.Error { 13 | return types.NewError(types.CodeBandwidthInfoNotFound, fmt.Sprintf("bandwidth info is not found")) 14 | } 15 | 16 | // ErrBlockInfoNotFound - error if last block info is not found 17 | func ErrBlockInfoNotFound() sdk.Error { 18 | return types.NewError(types.CodeBlockInfoNotFound, fmt.Sprintf("block info is not found")) 19 | } 20 | 21 | // ErrAppBandwidthInfoNotFound - error if app bandwidth info is not found 22 | func ErrAppBandwidthInfoNotFound() sdk.Error { 23 | return types.NewError(types.CodeAppBandwidthInfoNotFound, fmt.Sprintf("app bandwidth info is not found")) 24 | } 25 | -------------------------------------------------------------------------------- /x/global/model/ir.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | // sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/types" 7 | ) 8 | 9 | // GlobalTimeIR - global time 10 | type GlobalTimeIR struct { 11 | ChainStartTime int64 `json:"chain_start_time"` 12 | LastBlockTime int64 `json:"last_block_time"` 13 | PastMinutes int64 `json:"past_minutes"` 14 | } 15 | 16 | // GlobalTimeEventsIR - events, pk: UnixTime 17 | type GlobalTimeEventsIR struct { 18 | UnixTime int64 `json:"unix_time"` 19 | TimeEventList types.TimeEventList `json:"time_event_list"` 20 | } 21 | 22 | // GlobalTablesIR - state 23 | type GlobalTablesIR struct { 24 | Version int `json:"version"` 25 | GlobalTimeEventLists []GlobalTimeEventsIR `json:"global_time_event_lists"` 26 | Time GlobalTimeIR `json:"time"` 27 | } 28 | -------------------------------------------------------------------------------- /types/pools.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // inflation 5 | InflationDeveloperPool PoolName = "inflation/developer" 6 | InflationValidatorPool PoolName = "inflation/validator" 7 | InflationConsumptionPool PoolName = "inflation/consumption" 8 | 9 | // account 10 | AccountVestingPool PoolName = "account/vesting" 11 | 12 | // vote 13 | VoteStakeInPool PoolName = "vote/stake-in" 14 | VoteStakeReturnPool PoolName = "vote/stake-return" 15 | VoteFrictionPool PoolName = "vote/friction" 16 | 17 | // developer 18 | DevIDAReservePool PoolName = "dev/ida-reserve-pool" 19 | ) 20 | 21 | func ListPools() []PoolName { 22 | return []PoolName{ 23 | InflationDeveloperPool, 24 | InflationValidatorPool, 25 | InflationConsumptionPool, 26 | AccountVestingPool, 27 | VoteStakeInPool, 28 | VoteStakeReturnPool, 29 | VoteFrictionPool, 30 | DevIDAReservePool, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /param/keeper.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | //go:generate mockery -name ParamKeeper 4 | 5 | import ( 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | type ParamKeeper interface { 10 | GetPostParam(ctx sdk.Context) (*PostParam, sdk.Error) 11 | GetDeveloperParam(ctx sdk.Context) (*DeveloperParam, sdk.Error) 12 | GetVoteParam(ctx sdk.Context) *VoteParam 13 | GetProposalParam(ctx sdk.Context) (*ProposalParam, sdk.Error) 14 | GetValidatorParam(ctx sdk.Context) *ValidatorParam 15 | GetBandwidthParam(ctx sdk.Context) (*BandwidthParam, sdk.Error) 16 | GetAccountParam(ctx sdk.Context) *AccountParam 17 | GetGlobalAllocationParam(ctx sdk.Context) *GlobalAllocationParam 18 | GetPriceParam(ctx sdk.Context) *PriceParam 19 | GetReputationParam(ctx sdk.Context) *ReputationParam 20 | UpdateGlobalGrowthRate(ctx sdk.Context, growthRate sdk.Dec) sdk.Error 21 | } 22 | 23 | var _ ParamKeeper = ParamHolder{} 24 | -------------------------------------------------------------------------------- /x/developer/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | ) 6 | 7 | // Register concrete types on wire codec 8 | func RegisterWire(cdc *wire.Codec) { 9 | cdc.RegisterConcrete(DeveloperRegisterMsg{}, "lino/devRegister", nil) 10 | cdc.RegisterConcrete(DeveloperUpdateMsg{}, "lino/devUpdate", nil) 11 | cdc.RegisterConcrete(DeveloperRevokeMsg{}, "lino/devRevoke", nil) 12 | cdc.RegisterConcrete(IDAIssueMsg{}, "lino/IDAIssue", nil) 13 | cdc.RegisterConcrete(IDAMintMsg{}, "lino/IDAMint", nil) 14 | cdc.RegisterConcrete(IDATransferMsg{}, "lino/IDATransfer", nil) 15 | cdc.RegisterConcrete(IDAAuthorizeMsg{}, "lino/IDAAuthorize", nil) 16 | cdc.RegisterConcrete(UpdateAffiliatedMsg{}, "lino/UpdateAffiliated", nil) 17 | } 18 | 19 | var ModuleCdc = wire.New() 20 | 21 | func init() { 22 | RegisterWire(ModuleCdc) 23 | wire.RegisterCrypto(ModuleCdc) 24 | ModuleCdc.Seal() 25 | } 26 | -------------------------------------------------------------------------------- /types/ida.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // IDAStr - string representation of the number of IDA. 8 | // same as coin, support at most 5 digits precision(log10(Decimals)). 9 | type IDAStr string 10 | 11 | // MiniIDA is an integer. 12 | // 100000 MiniIDA = one IDA(Decimals). 13 | type MiniIDA = sdk.Int 14 | 15 | func (i IDAStr) ToMiniIDA() (MiniIDA, sdk.Error) { 16 | dec, err := sdk.NewDecFromStr(string(i)) 17 | if err != nil { 18 | return sdk.NewInt(0), ErrInvalidIDAAmount() 19 | } 20 | if dec.GT(UpperBoundRat) { 21 | return sdk.NewInt(0), ErrInvalidIDAAmount() 22 | } 23 | if dec.LT(LowerBoundRat) { 24 | return sdk.NewInt(0), ErrInvalidIDAAmount() 25 | } 26 | return dec.MulInt64(Decimals).RoundInt(), nil 27 | } 28 | 29 | func MiniIDAToMiniDollar(amount MiniIDA, miniIDAPrice MiniDollar) MiniDollar { 30 | return MiniDollar{miniIDAPrice.Mul(amount)} 31 | } 32 | -------------------------------------------------------------------------------- /client/broadcastcmd.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | 7 | // "strings" 8 | 9 | "github.com/spf13/cobra" 10 | // "github.com/spf13/viper" 11 | "github.com/cosmos/cosmos-sdk/codec" 12 | 13 | linotypes "github.com/lino-network/lino/types" 14 | ) 15 | 16 | // GetCmdBoradcast - 17 | func GetCmdBroadcast(cdc *codec.Codec) *cobra.Command { 18 | cmd := &cobra.Command{ 19 | Use: "broadcast", 20 | Short: "broadcast ", 21 | Args: cobra.ExactArgs(1), 22 | RunE: func(cmd *cobra.Command, args []string) error { 23 | ctx := NewCoreBroadcastContextFromViper().WithTxEncoder(linotypes.TxEncoder(cdc)) 24 | hexstr := args[0] 25 | hexbytes, err := hex.DecodeString(hexstr) 26 | if err != nil { 27 | return err 28 | } 29 | res, err := ctx.BroadcastTx(hexbytes) 30 | if err != nil { 31 | return err 32 | } 33 | fmt.Println(res.String()) 34 | return nil 35 | }, 36 | } 37 | return cmd 38 | } 39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.12.9 4 | install: 5 | - make get_tools 6 | - make get_golangci_lint 7 | script: 8 | - make lint 9 | - make build 10 | - make install 11 | - make test 12 | # safelist 13 | branches: 14 | only: 15 | - master 16 | notifications: 17 | slack: 18 | secure: QgDJp3M8MEVdU8EywqT+hq3YTWhL1o8v7MvVjJZV3D+FdS+2QmpSoF6v4olu633ps7F8b2g3Mkq7bM2U0khPvhnXXutfM/5x8Gd2V7G9+/fXlNxUMty3TA5ACbUbvJhveU4xZuXto52z7gXS4aCUQItQyxSlJsdAYJHQTgWOPX/lFSzR2yRQZUC1zs2gHg0FUVN6sBb3DzB0ui6tkM+0W0j60GScs4fnV0j/VuywEio4wGE4SpFZHptPYsPkpXiO6KxjCpUoMOOtbuzU5KPSZH5xeJpKVJhIoH9znfYXJyxXp1PJUQrg/gHD0O7RJYW3dYP51dYnt0AxROoAskkINWkoCj/zaWdqMdNaH5+w6OsOcjI4h3mej2Fuj2Jdjb6xJ4WNwL9Q6vhj8vlrK38KwMuAXVq6b1VXF9XQLJhBN991UmqH44JD6a9VlkX+lmoWefICbYNQJELOXIyC/+2yO0LGr83eojo/4GAdxtz4QlcN20cO7F5FT0ftqD1mRPCSSHMSLbes7TrlmbDpBn2/6GkOEFmtAh+pM46drnTrW9aAyrQzA/M8SSTtL61kHtgt3xGodllISQmmmgpszDuoHm4sTkZ+4ZJPgZ5dxmkwx8ab4qV+VVdnOCde1gGlqC+DeqoAjT0BnWeWvEwaMoAf8QBIc34adLfXdSeEVEWqvps= 19 | -------------------------------------------------------------------------------- /types/dec_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | // add test for NewDecFromRat 11 | func TestDecFromRat(t *testing.T) { 12 | assert := assert.New(t) 13 | rst := NewDecFromRat(1, 3) 14 | assert.Equal(sdk.MustNewDecFromStr("0.333333333333333333"), rst) 15 | } 16 | 17 | // precision lost case. 18 | // NOTE(yumin): this test case does not guarantee anything, instead, it shows 19 | // a case where precision can be lost if you do: 20 | // rst = (a / b) * c 21 | // instead of, 22 | // rst = (a * c) / b 23 | // we should use the latter form throughout the project, if possible, namely @mul-first-form. 24 | func TestErrors(t *testing.T) { 25 | assert := assert.New(t) 26 | expected := NewDecFromRat(316250000, 63) 27 | a := sdk.NewDec(316250000) 28 | b := sdk.NewDec(63) 29 | ratio := sdk.NewDec(1).Quo(b) 30 | rst := a.Mul(ratio) 31 | assert.NotEqual(expected, rst) 32 | } 33 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestUpdateDeveloper.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestGetLiveDeveloper/All_developers.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test2", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestGetLiveDeveloper/All_developers.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test2", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestDoesDeveloperExist.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/vote/model/golden/TestVoteStoreSuite/TestGetSetVoter.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "user1", 5 | "val": { 6 | "type": "lino/voter", 7 | "value": { 8 | "username": "user1", 9 | "lino_stake": { 10 | "amount": "123" 11 | }, 12 | "last_power_change_at": "777", 13 | "interest": { 14 | "amount": "234" 15 | }, 16 | "duty": "2", 17 | "frozen_amount": { 18 | "amount": "9" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "1", 25 | "key": "user2", 26 | "val": { 27 | "type": "lino/voter", 28 | "value": { 29 | "username": "user2", 30 | "lino_stake": { 31 | "amount": "345" 32 | }, 33 | "last_power_change_at": "888", 34 | "interest": { 35 | "amount": "456" 36 | }, 37 | "duty": "2", 38 | "frozen_amount": { 39 | "amount": "12" 40 | } 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestUpdateDeveloper/Fail_developer_deleted.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/price/handler.go: -------------------------------------------------------------------------------- 1 | package price 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | // linotypes "github.com/lino-network/lino/types" 10 | types "github.com/lino-network/lino/x/price/types" 11 | ) 12 | 13 | type FeedPriceMsg = types.FeedPriceMsg 14 | 15 | // NewHandler - Handle all "price" type messages. 16 | func NewHandler(pm PriceKeeper) sdk.Handler { 17 | return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { 18 | switch msg := msg.(type) { 19 | case FeedPriceMsg: 20 | return handleFeedPriceMsg(ctx, msg, pm) 21 | default: 22 | errMsg := fmt.Sprintf("unknown price msg type: %v", reflect.TypeOf(msg).Name()) 23 | return sdk.ErrUnknownRequest(errMsg).Result() 24 | } 25 | } 26 | } 27 | 28 | // handleFeedPriceMsg feed price message 29 | func handleFeedPriceMsg(ctx sdk.Context, msg FeedPriceMsg, pm PriceKeeper) sdk.Result { 30 | err := pm.FeedPrice(ctx, msg.Username, msg.Price) 31 | if err != nil { 32 | return err.Result() 33 | } 34 | return sdk.Result{} 35 | } 36 | -------------------------------------------------------------------------------- /docs/core/account.md: -------------------------------------------------------------------------------- 1 | # Account 2 | Account on Lino Blockchain has a global unique username. Except genesis account, user should send register msg to create a new account. To prevent the account spam attack, each new account should have a referrer who pays for the registration fee for it. The genesis account referrer is itself. The registration fee will be added to the developer inflation pool. The register msg should also provides three public keys. After the registration blockchain recognizes user behavior authorization by checking three public keys. 3 | 4 | Besides three public keys, each account has following parameters: 5 | 6 | - Balance: amount of LINO. 7 | - Coin day: fully charged coin day. 8 | - Number of balance history: Number of balance history. 9 | - Grant public keys: the public key this account grant permission to. 10 | - Sequence number: the number of transaction signed by the account owner. 11 | - Reward: statistic of reward received. 12 | - Pending coin day list: received LINO still charging the coin day, see coin day for more details. -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestUpdateDeveloper/Fail_developer_doesnt_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example goreleaser.yaml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | # 4 | env: 5 | - GO111MODULE=on 6 | before: 7 | hooks: 8 | # you may remove this if you don't use vgo 9 | # go mod tidy is flaky with go get. 10 | # - go mod tidy 11 | # you may remove this if you don't need go generate 12 | # - go generate ./... 13 | builds: 14 | - 15 | id: "linocli" 16 | main: ./cmd/linocli/main.go 17 | binary: linocli 18 | env: 19 | - CGO_ENABLED=0 20 | goos: 21 | - linux 22 | - darwin 23 | - windows 24 | goarch: 25 | - amd64 26 | - arm 27 | archives: 28 | - replacements: 29 | darwin: Darwin 30 | linux: Linux 31 | windows: Windows 32 | 386: i386 33 | amd64: x86_64 34 | checksum: 35 | name_template: 'checksums.txt' 36 | snapshot: 37 | name_template: "{{ .Tag }}-next" 38 | changelog: 39 | sort: asc 40 | filters: 41 | exclude: 42 | - '^docs:' 43 | - '^test:' 44 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestDoesDeveloperExist/Developer_does_not_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestDoesDeveloperExist/Developer_exist_deleted.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_even_distribution.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/bandwidth/keeper.go: -------------------------------------------------------------------------------- 1 | package bandwidth 2 | 3 | //go:generate mockery -name BandwidthKeeper 4 | 5 | import ( 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/cosmos/cosmos-sdk/x/auth" 8 | 9 | linotypes "github.com/lino-network/lino/types" 10 | "github.com/lino-network/lino/x/bandwidth/manager" 11 | "github.com/lino-network/lino/x/bandwidth/model" 12 | ) 13 | 14 | type BandwidthKeeper interface { 15 | InitGenesis(ctx sdk.Context) error 16 | DecayMaxMPS(ctx sdk.Context) sdk.Error 17 | ReCalculateAppBandwidthInfo(ctx sdk.Context) sdk.Error 18 | CheckBandwidth(ctx sdk.Context, addr sdk.AccAddress, fee auth.StdFee) sdk.Error 19 | EndBlocker(ctx sdk.Context) sdk.Error 20 | BeginBlocker(ctx sdk.Context) sdk.Error 21 | 22 | // getter 23 | GetBandwidthInfo(ctx sdk.Context) (*model.BandwidthInfo, sdk.Error) 24 | GetBlockInfo(ctx sdk.Context) (*model.BlockInfo, sdk.Error) 25 | GetAppBandwidthInfo(ctx sdk.Context, accKey linotypes.AccountKey) (*model.AppBandwidthInfo, sdk.Error) 26 | } 27 | 28 | var _ BandwidthKeeper = manager.BandwidthManager{} 29 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestDoesDeveloperExist/Developer_exists_not_deleted.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_even_distribution.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestUpdateDeveloper/Success.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "test website", 14 | "description": "test description", 15 | "app_meta_data": "test meta", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test-deleted", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test-deleted", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": true, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/global/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | types "github.com/lino-network/lino/types" 8 | ) 9 | 10 | func NewDumper(store GlobalStorage, options ...testutils.OptionCodec) *testutils.Dumper { 11 | dumper := testutils.NewDumper(store.key, store.cdc, options...) 12 | dumper.RegisterType(&types.TimeEventList{}, "lino/global/eventlist", TimeEventListSubStore) 13 | dumper.RegisterType(&GlobalTime{}, "lino/global/time", TimeSubStore) 14 | dumper.RegisterType(&[]EventError{}, "lino/global/eventerr", EventErrorSubStore) 15 | dumper.RegisterType(&[]types.BCEventErr{}, "lino/global/bceventerr", BCErrorSubStore) 16 | return dumper 17 | } 18 | 19 | func DumpToFile(ctx sdk.Context, store GlobalStorage, filepath string) { 20 | dumper := NewDumper(store) 21 | dumper.DumpToFile(ctx, filepath) 22 | } 23 | 24 | func LoadFromFile(ctx sdk.Context, store GlobalStorage, filepath string) { 25 | dumper := NewDumper(store) 26 | dumper.LoadFromFile(ctx, filepath) 27 | } 28 | -------------------------------------------------------------------------------- /x/vote/model/golden/TestVoteStoreSuite/TestGetSetLinoStakeStats.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "2", 4 | "key": "1", 5 | "val": { 6 | "type": "lino/stakestats", 7 | "value": { 8 | "total_consumption_friction": { 9 | "amount": "123" 10 | }, 11 | "unclaimed_friction": { 12 | "amount": "456" 13 | }, 14 | "total_lino_power": { 15 | "amount": "789" 16 | }, 17 | "unclaimed_lino_power": { 18 | "amount": "999" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "2", 25 | "key": "2", 26 | "val": { 27 | "type": "lino/stakestats", 28 | "value": { 29 | "total_consumption_friction": { 30 | "amount": "888" 31 | }, 32 | "unclaimed_friction": { 33 | "amount": "888" 34 | }, 35 | "total_lino_power": { 36 | "amount": "888" 37 | }, 38 | "unclaimed_lino_power": { 39 | "amount": "888" 40 | } 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /docs/core/consensus.md: -------------------------------------------------------------------------------- 1 | # Consensus 2 | 3 | ## Tendermint 4 | 5 | Currently the Lino Blockchain is built on the consensus engine: Tendermint. Tendermint is software for securely and consistently replicating an application on many machines. It implements the Byzantine fault tolerance (BFT) which tolerate up to ⅓ of validators failed in arbitrary ways. To achieve the better performance we predefine the size of validator set is 22. The validator can be changed by the locked Lino Stake. 6 | 7 | For more information about tendermint, please refer to [here](https://tendermint.com/docs/). 8 | 9 | ## ABCI and Cosmos SDK 10 | 11 | The tendermint consensus engine communicates with the Lino Blockchain via a socket protocol that satisfies the ABCI. Lino Blockchain implement ABCI through Cosmos SDK, which is a platform for building multi-asset Proof-of-Stake cryptocurrencies. The goals of the SDK are to abstract away the complexities of building a Tendermint ABCI application in Golang and to provide a framework for building interoperable blockchain applications in the Cosmos Network. 12 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Fail_error_when_move_coin_to_account.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Fail_error_when_move_coin_to_account.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeIn/stake_in_minimum_requirement.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "user1", 5 | "val": { 6 | "type": "lino/voter", 7 | "value": { 8 | "username": "user1", 9 | "lino_stake": { 10 | "amount": "100000000" 11 | }, 12 | "last_power_change_at": "100", 13 | "interest": { 14 | "amount": "0" 15 | }, 16 | "duty": "0", 17 | "frozen_amount": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "2", 25 | "key": "0", 26 | "val": { 27 | "type": "lino/stakestats", 28 | "value": { 29 | "total_consumption_friction": { 30 | "amount": "0" 31 | }, 32 | "unclaimed_friction": { 33 | "amount": "0" 34 | }, 35 | "total_lino_power": { 36 | "amount": "100000000" 37 | }, 38 | "unclaimed_lino_power": { 39 | "amount": "100000000" 40 | } 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestStakeInFor/stake_in_minimum_requirement.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "user2", 5 | "val": { 6 | "type": "lino/voter", 7 | "value": { 8 | "username": "user2", 9 | "lino_stake": { 10 | "amount": "100000000" 11 | }, 12 | "last_power_change_at": "100", 13 | "interest": { 14 | "amount": "0" 15 | }, 16 | "duty": "0", 17 | "frozen_amount": { 18 | "amount": "0" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "2", 25 | "key": "0", 26 | "val": { 27 | "type": "lino/stakestats", 28 | "value": { 29 | "total_consumption_friction": { 30 | "amount": "0" 31 | }, 32 | "unclaimed_friction": { 33 | "amount": "0" 34 | }, 35 | "total_lino_power": { 36 | "amount": "100000000" 37 | }, 38 | "unclaimed_lino_power": { 39 | "amount": "100000000" 40 | } 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /param/event.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // ChangeParamEvent - change parameter event 8 | type ChangeParamEvent struct { 9 | Param Parameter `json:"param"` 10 | } 11 | 12 | // Execute - execute change parameter event 13 | func (cpe ChangeParamEvent) Execute(ctx sdk.Context, ph ParamHolder) sdk.Error { 14 | parameter := cpe.Param 15 | switch parameter := parameter.(type) { 16 | case GlobalAllocationParam: 17 | return ph.setGlobalAllocationParam(ctx, ¶meter) 18 | case VoteParam: 19 | return ph.setVoteParam(ctx, ¶meter) 20 | case ProposalParam: 21 | return ph.setProposalParam(ctx, ¶meter) 22 | case DeveloperParam: 23 | return ph.setDeveloperParam(ctx, ¶meter) 24 | case ValidatorParam: 25 | return ph.setValidatorParam(ctx, ¶meter) 26 | case BandwidthParam: 27 | return ph.setBandwidthParam(ctx, ¶meter) 28 | case AccountParam: 29 | return ph.setAccountParam(ctx, ¶meter) 30 | case PostParam: 31 | return ph.setPostParam(ctx, ¶meter) 32 | default: 33 | return ErrInvalidaParameter() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/post/publish_test.go: -------------------------------------------------------------------------------- 1 | package post 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/lino-network/lino/test" 8 | // "github.com/lino-network/lino/types" 9 | // post "github.com/lino-network/lino/x/post" 10 | "github.com/tendermint/tendermint/crypto/secp256k1" 11 | ) 12 | 13 | // test publish a normal post 14 | func TestNormalPublish(t *testing.T) { 15 | newAccountTransactionPriv := secp256k1.GenPrivKey() 16 | newAccountName := "newuser" 17 | postID1 := "New Post 1" 18 | postID2 := "New Post 2" 19 | // recover some coin day 20 | baseT := time.Unix(0, 0).Add(3600 * time.Second) 21 | baseTime := baseT.Unix() 22 | lb := test.NewTestLinoBlockchain(t, test.DefaultNumOfVal, baseT) 23 | 24 | test.CreateAccount(t, newAccountName, lb, 0, 25 | secp256k1.GenPrivKey(), newAccountTransactionPriv, "100") 26 | 27 | test.CreateTestPost( 28 | t, lb, newAccountName, postID1, 1, newAccountTransactionPriv, baseTime) 29 | test.SimulateOneBlock(lb, baseTime+test.PostIntervalSec) 30 | test.CreateTestPost( 31 | t, lb, newAccountName, postID2, 2, newAccountTransactionPriv, baseTime+test.PostIntervalSec) 32 | } 33 | -------------------------------------------------------------------------------- /x/global/model/golden/TestGlobalStoreSuite/TestGetSetDelTimeEventList.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "123", 5 | "val": { 6 | "type": "lino/global/eventlist", 7 | "value": { 8 | "events": [ 9 | { 10 | "type": "lino/testevent", 11 | "value": { 12 | "name": "event1" 13 | } 14 | }, 15 | { 16 | "type": "lino/testevent", 17 | "value": { 18 | "name": "event2" 19 | } 20 | }, 21 | { 22 | "type": "lino/testevent", 23 | "value": { 24 | "name": "event3" 25 | } 26 | } 27 | ] 28 | } 29 | } 30 | }, 31 | { 32 | "prefix": "0", 33 | "key": "456", 34 | "val": { 35 | "type": "lino/global/eventlist", 36 | "value": { 37 | "events": [ 38 | { 39 | "type": "lino/testevent", 40 | "value": { 41 | "name": "event4" 42 | } 43 | } 44 | ] 45 | } 46 | } 47 | } 48 | ] 49 | -------------------------------------------------------------------------------- /x/vote/model/voter.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | linotypes "github.com/lino-network/lino/types" 5 | "github.com/lino-network/lino/x/vote/types" 6 | ) 7 | 8 | // Voter - a voter in blockchain is account with voter deposit, who can vote for a proposal 9 | type Voter struct { 10 | Username linotypes.AccountKey `json:"username"` 11 | LinoStake linotypes.Coin `json:"lino_stake"` 12 | LastPowerChangeAt int64 `json:"last_power_change_at"` 13 | Interest linotypes.Coin `json:"interest"` 14 | Duty types.VoterDuty `json:"duty"` 15 | FrozenAmount linotypes.Coin `json:"frozen_amount"` 16 | } 17 | 18 | // LinoStakeStat - records the information needed by 19 | // lino power deposit, update and store daily. 20 | type LinoStakeStat struct { 21 | TotalConsumptionFriction linotypes.Coin `json:"total_consumption_friction"` 22 | UnclaimedFriction linotypes.Coin `json:"unclaimed_friction"` 23 | TotalLinoStake linotypes.Coin `json:"total_lino_power"` 24 | UnclaimedLinoStake linotypes.Coin `json:"unclaimed_lino_power"` 25 | } 26 | -------------------------------------------------------------------------------- /x/reputation/keeper.go: -------------------------------------------------------------------------------- 1 | package reputation 2 | 3 | //go:generate mockery -name ReputationKeeper 4 | 5 | import ( 6 | codec "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | "github.com/lino-network/lino/types" 10 | ) 11 | 12 | type ReputationKeeper interface { 13 | // upon donation, record this donation and return the impact factor. 14 | DonateAt( 15 | ctx sdk.Context, 16 | username types.AccountKey, 17 | post types.Permlink, 18 | amount types.MiniDollar) (types.MiniDollar, sdk.Error) 19 | 20 | // get user's latest reputation, which is the largest impact factor a user can 21 | // make in a window. 22 | GetReputation(ctx sdk.Context, username types.AccountKey) (types.MiniDollar, sdk.Error) 23 | 24 | // update game status on block end. 25 | Update(ctx sdk.Context) sdk.Error 26 | 27 | // return the current round start time 28 | GetCurrentRound(ctx sdk.Context) (int64, sdk.Error) 29 | 30 | // import/export this module to files 31 | ExportToFile(ctx sdk.Context, cdc *codec.Codec, file string) error 32 | ImportFromFile(ctx sdk.Context, cdc *codec.Codec, file string) error 33 | } 34 | -------------------------------------------------------------------------------- /x/developer/model/dumper.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/lino-network/lino/testutils" 7 | ) 8 | 9 | func NewDeveloperDumper(store DeveloperStorage) *testutils.Dumper { 10 | dumper := testutils.NewDumper(store.key, store.cdc) 11 | dumper.RegisterType(&Developer{}, "lino/developer", DeveloperSubstore) 12 | dumper.RegisterType(&AppIDA{}, "lino/appida", IdaSubstore) 13 | dumper.RegisterType(&Role{}, "lino/role", UserRoleSubstore) 14 | dumper.RegisterType(&IDABank{}, "lino/bank", IdaBalanceSubstore) 15 | dumper.RegisterType(&ReservePool{}, "lino/reservepool", ReservePoolSubstore) 16 | dumper.RegisterType(&AppIDAStats{}, "lino/appidastats", IdaStatsSubstore) 17 | dumper.RegisterRawString(AffiliatedAccSubstore) 18 | return dumper 19 | } 20 | 21 | func DumpToFile(ctx sdk.Context, store DeveloperStorage, filepath string) { 22 | dumper := NewDeveloperDumper(store) 23 | dumper.DumpToFile(ctx, filepath) 24 | } 25 | 26 | func LoadFromFile(ctx sdk.Context, store DeveloperStorage, filepath string) { 27 | dumper := NewDeveloperDumper(store) 28 | dumper.LoadFromFile(ctx, filepath) 29 | } 30 | -------------------------------------------------------------------------------- /x/post/querier.go: -------------------------------------------------------------------------------- 1 | package post 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | 8 | linotypes "github.com/lino-network/lino/types" 9 | "github.com/lino-network/lino/utils" 10 | "github.com/lino-network/lino/x/post/types" 11 | ) 12 | 13 | // creates a querier for post REST endpoints 14 | func NewQuerier(pm PostKeeper) sdk.Querier { 15 | cdc := wire.New() 16 | wire.RegisterCrypto(cdc) 17 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { 18 | switch path[0] { 19 | case types.QueryPostInfo: 20 | return utils.NewQueryResolver(1, func(args ...string) (interface{}, sdk.Error) { 21 | return pm.GetPost(ctx, linotypes.Permlink(args[0])) 22 | })(ctx, cdc, path) 23 | case types.QueryConsumptionWindow: 24 | return utils.NewQueryResolver(0, func(args ...string) (interface{}, sdk.Error) { 25 | return pm.GetComsumptionWindow(ctx), nil 26 | })(ctx, cdc, path) 27 | default: 28 | return nil, sdk.ErrUnknownRequest("unknown post query endpoint") 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /x/price/model/wmprice.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | linotypes "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // FedPrice is record of price fed by validators. 8 | type FedPrice struct { 9 | Validator linotypes.AccountKey `json:"validator"` 10 | Price linotypes.MiniDollar `json:"price"` 11 | UpdateAt int64 `json:"update_at"` 12 | } 13 | 14 | // TimePrice is time + price 15 | type TimePrice struct { 16 | Price linotypes.MiniDollar `json:"price"` 17 | UpdateAt int64 `json:"update_at"` 18 | } 19 | 20 | // FedRecord - power and price. 21 | type FedRecord struct { 22 | Validator linotypes.AccountKey `json:"validator"` 23 | Price linotypes.MiniDollar `json:"price"` 24 | Power linotypes.Coin `json:"power"` 25 | UpdateAt int64 `json:"update_at"` 26 | } 27 | 28 | // FeedHistory the history of price feed of one price update. 29 | // Used by querier for now and governance in future. 30 | type FeedHistory struct { 31 | Price linotypes.MiniDollar `json:"price"` 32 | Feeded []FedRecord `json:"feeded"` 33 | UpdateAt int64 `json:"update_at"` 34 | } 35 | -------------------------------------------------------------------------------- /utils/querier.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | 6 | wire "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | linotypes "github.com/lino-network/lino/types" 10 | ) 11 | 12 | // query store 13 | type StoreQuerier = func(args ...string) (interface{}, sdk.Error) 14 | 15 | // return query result 16 | type QueryResolver = func(ctx sdk.Context, cdc *wire.Codec, path []string) ([]byte, sdk.Error) 17 | 18 | func NewQueryResolver(numArgs int, resolver StoreQuerier) QueryResolver { 19 | return func(ctx sdk.Context, cdc *wire.Codec, path []string) ([]byte, sdk.Error) { 20 | if len(path) < 1 { 21 | return nil, linotypes.ErrQueryFailed("invalid query") 22 | } 23 | substore := path[0] 24 | path = path[1:] 25 | if err := linotypes.CheckPathContentAndMinLength(path, numArgs); err != nil { 26 | return nil, err 27 | } 28 | rst, err := resolver(path...) 29 | if err != nil { 30 | return nil, err 31 | } 32 | res, marshalErr := cdc.MarshalJSON(rst) 33 | if marshalErr != nil { 34 | return nil, linotypes.ErrQueryFailed(fmt.Sprintf("query %s failed", substore)) 35 | } 36 | return res, nil 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/core/reputation.md: -------------------------------------------------------------------------------- 1 | # Reputation 2 | 3 | In Lino Blockchain, the content creator can get content bonus from content creator inflation pool, which is huge incentive for content creator. However, someone may make fake donation to his own content to get bonus from the inflation pool. To prevent bad content stealing bonus, the account on blockchain will have a reputation score with it. The reputation score consists of two parts: free score and customer score. 4 | 5 | The free score comes from stake in. A certain percentage of free score will be added to user’s reputation if user stake in and removed once user stake out. 6 | 7 | The default customer score is 1 LINO for all accounts. To increase the customer score, one should be in order front of donors to daily top N content. The total donation power a user can spend on a post is limited by his reputation. 8 | 9 | For each donation, based on user’s reputation, it will add sum of the reputation of the post. For each report, it will minus sum of the reputation of the post. The penalty score of a post is negative of sum of reputation divided by predefined hard cap. The penalty score will affect the content bonus get from inflation pool. 10 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestUpdatePriceSlash/no_validator_feed_at_init_and_no_slash.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "1200", 10 | "update_at": "0" 11 | }, 12 | { 13 | "price": "1200", 14 | "update_at": "3600" 15 | } 16 | ] 17 | } 18 | }, 19 | { 20 | "prefix": "2", 21 | "key": "", 22 | "val": { 23 | "type": "lino/price/current", 24 | "value": { 25 | "price": "1200", 26 | "update_at": "3600" 27 | } 28 | } 29 | }, 30 | { 31 | "prefix": "3", 32 | "key": "", 33 | "val": { 34 | "type": "lino/price/lastvals", 35 | "value": [ 36 | "val1", 37 | "val2", 38 | "val3" 39 | ] 40 | } 41 | }, 42 | { 43 | "prefix": "4", 44 | "key": "", 45 | "val": { 46 | "type": "lino/price/feedhistory", 47 | "value": [ 48 | { 49 | "price": "1200", 50 | "feeded": null, 51 | "update_at": "3600" 52 | } 53 | ] 54 | } 55 | } 56 | ] 57 | -------------------------------------------------------------------------------- /x/global/keeper.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | //go:generate mockery -name GlobalKeeper 4 | 5 | import ( 6 | codec "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | linotypes "github.com/lino-network/lino/types" 10 | "github.com/lino-network/lino/x/global/model" 11 | ) 12 | 13 | // GlobalKeeper - aka global event manager. 14 | type GlobalKeeper interface { 15 | InitGenesis(ctx sdk.Context) 16 | 17 | // blockchain scheduled events. 18 | OnBeginBlock(ctx sdk.Context) 19 | OnEndBlock(ctx sdk.Context) 20 | 21 | // module events 22 | RegisterEventAtTime(ctx sdk.Context, unixTime int64, event linotypes.Event) sdk.Error 23 | ExecuteEvents(ctx sdk.Context, exec linotypes.EventExec) 24 | 25 | // Getter 26 | //// global time 27 | GetLastBlockTime(ctx sdk.Context) int64 28 | GetPastDay(ctx sdk.Context, unixTime int64) int64 29 | GetBCEventErrors(ctx sdk.Context) []linotypes.BCEventErr 30 | GetEventErrors(ctx sdk.Context) []model.EventError 31 | GetGlobalTime(ctx sdk.Context) model.GlobalTime 32 | 33 | // import export 34 | ImportFromFile(ctx sdk.Context, cdc *codec.Codec, filepath string) error 35 | ExportToFile(ctx sdk.Context, cdc *codec.Codec, filepath string) error 36 | } 37 | -------------------------------------------------------------------------------- /x/global/manager/golden/TestGlobalManagerSuite/TestImportExport.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "123486", 5 | "val": { 6 | "type": "lino/global/eventlist", 7 | "value": { 8 | "events": [ 9 | { 10 | "type": "lino/testevent", 11 | "value": { 12 | "id": "1" 13 | } 14 | }, 15 | { 16 | "type": "lino/testevent", 17 | "value": { 18 | "id": "2" 19 | } 20 | } 21 | ] 22 | } 23 | } 24 | }, 25 | { 26 | "prefix": "0", 27 | "key": "123501", 28 | "val": { 29 | "type": "lino/global/eventlist", 30 | "value": { 31 | "events": [ 32 | { 33 | "type": "lino/testevent", 34 | "value": { 35 | "id": "3" 36 | } 37 | } 38 | ] 39 | } 40 | } 41 | }, 42 | { 43 | "prefix": "1", 44 | "key": "", 45 | "val": { 46 | "type": "lino/global/time", 47 | "value": { 48 | "chain_start_time": "123456", 49 | "last_block_time": "123456", 50 | "past_minutes": "0" 51 | } 52 | } 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /x/reputation/repv2/encodergen/encodergen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | # This file was called GobCodeGen, but we found some un-deterministic spots in 6 | # gob, so we abandon it. As you can see, now it's a amigo(cdc) 7 | # marshal/unmarshal warpper. 8 | 9 | template = """ 10 | func decode$TYPE(data []byte) *TYPE { 11 | if data == nil { 12 | return nil 13 | } 14 | rst := &TYPE{} 15 | cdc.MustUnmarshalBinaryBare(data, rst) 16 | return rst 17 | } 18 | 19 | func encode$TYPE(dt *TYPE) []byte { 20 | if dt == nil { 21 | return nil 22 | } 23 | rst := cdc.MustMarshalBinaryBare(dt) 24 | return []byte(rst) 25 | } 26 | """ 27 | 28 | structs = ['userMeta', 'roundMeta', 'roundPostMeta', 'gameMeta'] 29 | 30 | 31 | def cap(word): 32 | return word[0].upper() + word[1:] 33 | 34 | 35 | def main(): 36 | if len(sys.argv) < 2: 37 | for type_name in structs: 38 | tmp = template.replace("$TYPE", cap(type_name)) 39 | print tmp.replace("TYPE", type_name) 40 | else: 41 | type_name = sys.argv[1] 42 | tmp = template.replace("$TYPE", cap(type_name)) 43 | print tmp.replace("TYPE", type_name) 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /client/flags.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | // nolint 8 | const ( 9 | FlagOffline = "offline" 10 | FlagChainID = "chain-id" 11 | FlagNode = "node" 12 | FlagHeight = "height" 13 | FlagTrustNode = "trust-node" 14 | FlagName = "name" 15 | FlagSequence = "sequence" 16 | FlagPrivKey = "priv-key" 17 | FlagPubKey = "pub-key" 18 | FlagFees = "fees" 19 | 20 | // Infra 21 | FlagProvider = "provider" 22 | FlagUsage = "usage" 23 | ) 24 | 25 | // PostCommands adds common flags for commands to post tx 26 | func PostCommands(cmds ...*cobra.Command) []*cobra.Command { 27 | for _, c := range cmds { 28 | c.Flags().Int64(FlagSequence, -1, "Sequence number to sign the tx") 29 | c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") 30 | c.Flags().String(FlagPrivKey, "", "Hex-encoded private key or encrypted file path(starting with @) to sign the transaction") 31 | c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") 32 | c.Flags().String(FlagFees, "", "Fees to pay along with transaction; eg: 1linocoin") 33 | c.Flags().Bool(FlagOffline, false, "Print Tx to stdout only") 34 | } 35 | return cmds 36 | } 37 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestRegisterDeveloper/Success.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test_username", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test_username", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "test website", 33 | "description": "test description", 34 | "app_meta_data": "test meta", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "5", 42 | "key": "test2", 43 | "val": { 44 | "type": "lino/role", 45 | "value": { 46 | "aa": "test2" 47 | } 48 | } 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /testsuites/ctx.go: -------------------------------------------------------------------------------- 1 | package testsuites 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/cosmos/cosmos-sdk/store" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/stretchr/testify/suite" 9 | abci "github.com/tendermint/tendermint/abci/types" 10 | "github.com/tendermint/tendermint/libs/log" 11 | dbm "github.com/tendermint/tm-db" 12 | ) 13 | 14 | type CtxTestSuite struct { 15 | suite.Suite 16 | ms sdk.CommitMultiStore 17 | height int64 18 | time time.Time 19 | Ctx sdk.Context 20 | } 21 | 22 | func (suite *CtxTestSuite) SetupCtx(height int64, t time.Time, keys ...*sdk.KVStoreKey) { 23 | db := dbm.NewMemDB() 24 | ms := store.NewCommitMultiStore(db) 25 | for _, key := range keys { 26 | ms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) 27 | } 28 | err := ms.LoadLatestVersion() 29 | suite.Require().Nil(err) 30 | suite.ms = ms 31 | suite.Ctx = sdk.NewContext( 32 | ms, abci.Header{ChainID: "Lino", Height: height, Time: t}, false, log.NewNopLogger()) 33 | suite.height = height 34 | suite.time = t 35 | } 36 | 37 | func (suite *CtxTestSuite) NextBlock(t time.Time) { 38 | suite.Ctx = sdk.NewContext( 39 | suite.ms, abci.Header{ 40 | ChainID: "Lino", Height: suite.height + 1, Time: t}, false, log.NewNopLogger()) 41 | suite.time = t 42 | } 43 | -------------------------------------------------------------------------------- /x/global/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/lino-network/lino/types" 8 | ) 9 | 10 | // ErrRegisterExpiredEvent - error when register event time is before current timestamp 11 | func ErrRegisterExpiredEvent(unixTime int64) sdk.Error { 12 | return types.NewError(types.CodeRegisterExpiredEvent, fmt.Sprintf("register event at expired time %v", unixTime)) 13 | } 14 | 15 | // ErrGetPastDay - error if get past day is negative 16 | func ErrGetPastDay() sdk.Error { 17 | return types.NewError(types.CodeFailedToGetAmountOfConsumptionExponent, "get past day failed") 18 | } 19 | 20 | // ErrParseEventCacheList - error if parse event cache list failed 21 | func ErrParseEventCacheList() sdk.Error { 22 | return types.NewError(types.CodeFailedToParseEventCacheList, "parse event list failed") 23 | } 24 | 25 | // ErrQueryFailed - error when query global store failed 26 | func ErrQueryFailed() sdk.Error { 27 | return types.NewError(types.CodeGlobalQueryFailed, fmt.Sprintf("query global store failed")) 28 | } 29 | 30 | // ErrRegisterInvalidEvent - 31 | func ErrRegisterInvalidEvent() sdk.Error { 32 | return types.NewError( 33 | types.CodeRegisterInvalidEvent, fmt.Sprintf("event is invalid, cannot be wired")) 34 | } 35 | -------------------------------------------------------------------------------- /x/account/model/golden/TestAccountStoreSuite/TestBank.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "\ufffd!N\ufffd\ufffd\ufffd֪'\ufffd\u001c\ufffd\ufffd\ufffd\ufffd\u000fS\ufffd\u0008\ufffd", 5 | "val": { 6 | "type": "lino/account/bank", 7 | "value": { 8 | "saving": { 9 | "amount": "2345" 10 | }, 11 | "pending": { 12 | "amount": "789" 13 | }, 14 | "public_key": { 15 | "type": "tendermint/PubKeySecp256k1", 16 | "value": "AoFqbXKmblwKVggqb8Cqo30gRKs9EfqwhOhuyOKlGCuD" 17 | }, 18 | "sequence": "456", 19 | "username": "user2" 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "1", 25 | "key": "\ufffd\ufffd\u0001phS\ufffdՖ\ufffd\ufffd\u0017\ufffd@\ufffd\\\ufffd\ufffd\ufffd\u0002", 26 | "val": { 27 | "type": "lino/account/bank", 28 | "value": { 29 | "saving": { 30 | "amount": "1234" 31 | }, 32 | "pending": { 33 | "amount": "0" 34 | }, 35 | "public_key": { 36 | "type": "tendermint/PubKeySecp256k1", 37 | "value": "Aot3u5m7vuxUOszkS6IZW5XYVu6ATvZsfSQIjtQo9tML" 38 | }, 39 | "sequence": "123", 40 | "username": "user1" 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /x/bandwidth/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | linotypes "github.com/lino-network/lino/types" 9 | ) 10 | 11 | // ErrInvalidMsgQuota - error when message fee is not valid 12 | func ErrInvalidMsgQuota() sdk.Error { 13 | return linotypes.NewError(linotypes.CodeInvalidMsgQuota, fmt.Sprintf("invalid message quota")) 14 | } 15 | 16 | // ErrInvalidExpectedMPS - error when message fee is not valid 17 | func ErrInvalidExpectedMPS() sdk.Error { 18 | return linotypes.NewError(linotypes.CodeInvalidExpectedMPS, fmt.Sprintf("invalid expected mps")) 19 | } 20 | 21 | // ErrAppBandwidthNotEnough - error when app bandwidth not enough 22 | func ErrAppBandwidthNotEnough() sdk.Error { 23 | return linotypes.NewError(linotypes.CodeAppBandwidthNotEnough, fmt.Sprintf("app bandwidth not enough")) 24 | } 25 | 26 | // ErrUserMsgFeeNotEnough - error when app bandwidth not enough 27 | func ErrUserMsgFeeNotEnough() sdk.Error { 28 | return linotypes.NewError(linotypes.CodeUserMsgFeeNotEnough, fmt.Sprintf("user message fee not enough")) 29 | } 30 | 31 | // ErrQueryFailed - error when query bandwidth store failed 32 | func ErrQueryFailed() sdk.Error { 33 | return linotypes.NewError(linotypes.CodeBandwidthQueryFailed, fmt.Sprintf("query bandwidth store failed")) 34 | } 35 | -------------------------------------------------------------------------------- /x/price/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | // "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/price/model" 13 | "github.com/lino-network/lino/x/price/types" 14 | ) 15 | 16 | func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: "Querying commands for the price module", 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | cmd.AddCommand(client.GetCommands( 25 | utils.SimpleQueryCmd( 26 | "current", 27 | "current", 28 | types.QuerierRoute, types.QueryPriceCurrent, 29 | 0, &linotypes.MiniDollar{})(cdc), 30 | utils.SimpleQueryCmd( 31 | "history", 32 | "history", 33 | types.QuerierRoute, types.QueryPriceHistory, 34 | 0, &([]model.FeedHistory{}))(cdc), 35 | utils.SimpleQueryCmd( 36 | "last-feed ", 37 | "last-feed ", 38 | types.QuerierRoute, types.QueryLastFeed, 39 | 1, &model.FedPrice{})(cdc), 40 | )...) 41 | return cmd 42 | } 43 | -------------------------------------------------------------------------------- /types/txencoder.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | cauth "github.com/cosmos/cosmos-sdk/x/auth" 7 | ) 8 | 9 | // Theses two functions must be paired, that if txEncoder use JSON format, 10 | // the txDecoder must use JSON format as well. 11 | // All libraries use use the TxEncoder below. 12 | 13 | // TxDecoder - default tx decoder, decode tx before authenticate handler 14 | func TxDecoder(cdc *wire.Codec) sdk.TxDecoder { 15 | return func(txBytes []byte) (tx sdk.Tx, err sdk.Error) { 16 | defer func() { 17 | if r := recover(); r != nil { 18 | err = sdk.ErrTxDecode("tx decode panic") 19 | } 20 | }() 21 | tx = cauth.StdTx{} 22 | 23 | if len(txBytes) == 0 { 24 | return nil, sdk.ErrTxDecode("txBytes are empty") 25 | } 26 | 27 | // StdTx.Msg is an interface. The concrete types 28 | // are registered by MakeTxCodec 29 | unmarshalErr := cdc.UnmarshalJSON(txBytes, &tx) 30 | if unmarshalErr != nil { 31 | return nil, sdk.ErrTxDecode("") 32 | } 33 | return tx, nil 34 | } 35 | } 36 | 37 | // TxDecoder - default tx decoder, decode tx before authenticate handler 38 | func TxEncoder(cdc *wire.Codec) sdk.TxEncoder { 39 | return func(tx sdk.Tx) ([]byte, error) { 40 | return cdc.MarshalJSON(tx) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /x/bandwidth/model/bandwidth.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | linotypes "github.com/lino-network/lino/types" 6 | ) 7 | 8 | // BandwidthInfo - stores info about the moving average of mps and max mps 9 | type BandwidthInfo struct { 10 | GeneralMsgEMA sdk.Dec `json:"general_msg_ema"` 11 | AppMsgEMA sdk.Dec `json:"app_msg_ema"` 12 | MaxMPS sdk.Dec `json:"max_mps"` 13 | } 14 | 15 | // BlockInfo - stores info about number of tx in last block 16 | type BlockInfo struct { 17 | TotalMsgSignedByApp int64 `json:"total_tx_signed_by_app"` 18 | TotalMsgSignedByUser int64 `json:"total_tx_signed_by_user"` 19 | CurMsgFee linotypes.Coin `json:"cur_msg_fee"` 20 | CurU sdk.Dec `json:"cur_u"` 21 | } 22 | 23 | // AppBandwidthInfo - stores info about each app's bandwidth 24 | type AppBandwidthInfo struct { 25 | Username linotypes.AccountKey `json:"username"` 26 | MaxBandwidthCredit sdk.Dec `json:"max_bandwidth_credit"` 27 | CurBandwidthCredit sdk.Dec `json:"cur_bandwidth_credit"` 28 | MessagesInCurBlock int64 `json:"messages_in_cur_block"` 29 | ExpectedMPS sdk.Dec `json:"expected_mps"` 30 | LastRefilledAt int64 `json:"last_refilled_at"` 31 | } 32 | -------------------------------------------------------------------------------- /x/account/model/golden/TestAccountStoreSuite/TestInfo.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "user1", 5 | "val": { 6 | "type": "lino/account/info", 7 | "value": { 8 | "username": "user1", 9 | "created_at": "123", 10 | "signing_key": { 11 | "type": "tendermint/PubKeySecp256k1", 12 | "value": "A6P8IUdt9DKrYCe3/Tflt7DBdgFokRcCKkixt+UbhjZ8" 13 | }, 14 | "transaction_key": { 15 | "type": "tendermint/PubKeySecp256k1", 16 | "value": "Aot3u5m7vuxUOszkS6IZW5XYVu6ATvZsfSQIjtQo9tML" 17 | }, 18 | "address": "cosmos1kreqzurg204at9595qtlwsyltjyehmgzrm2utg" 19 | } 20 | } 21 | }, 22 | { 23 | "prefix": "0", 24 | "key": "user2", 25 | "val": { 26 | "type": "lino/account/info", 27 | "value": { 28 | "username": "user2", 29 | "created_at": "456", 30 | "signing_key": { 31 | "type": "tendermint/PubKeySecp256k1", 32 | "value": "A+KW7obJ0BpKqUWmY33svTBxGdTfRhmOym7A5imWWwGm" 33 | }, 34 | "transaction_key": { 35 | "type": "tendermint/PubKeySecp256k1", 36 | "value": "AoFqbXKmblwKVggqb8Cqo30gRKs9EfqwhOhuyOKlGCuD" 37 | }, 38 | "address": "cosmos1j5s5a4lfu0t25f77rj6c0v4wpafa6z9g7ks5uw" 39 | } 40 | } 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestFeedPrice/succ_two_round.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "val1", 5 | "val": { 6 | "type": "lino/price/fedprice", 7 | "value": { 8 | "validator": "val1", 9 | "price": "400", 10 | "update_at": "600" 11 | } 12 | } 13 | }, 14 | { 15 | "prefix": "0", 16 | "key": "val2", 17 | "val": { 18 | "type": "lino/price/fedprice", 19 | "value": { 20 | "validator": "val2", 21 | "price": "500", 22 | "update_at": "600" 23 | } 24 | } 25 | }, 26 | { 27 | "prefix": "0", 28 | "key": "val3", 29 | "val": { 30 | "type": "lino/price/fedprice", 31 | "value": { 32 | "validator": "val3", 33 | "price": "600", 34 | "update_at": "600" 35 | } 36 | } 37 | }, 38 | { 39 | "prefix": "1", 40 | "key": "", 41 | "val": { 42 | "type": "lino/price/history", 43 | "value": [ 44 | { 45 | "price": "1200", 46 | "update_at": "0" 47 | } 48 | ] 49 | } 50 | }, 51 | { 52 | "prefix": "2", 53 | "key": "", 54 | "val": { 55 | "type": "lino/price/current", 56 | "value": { 57 | "price": "1200", 58 | "update_at": "0" 59 | } 60 | } 61 | } 62 | ] 63 | -------------------------------------------------------------------------------- /types/event.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // Event - event executed in app.go 8 | type Event interface{} 9 | 10 | // Minute -> TimeEventList 11 | type TimeEventList struct { 12 | Events []Event `json:"events"` 13 | } 14 | 15 | // EventError - event and errors 16 | // Module scheduled events 17 | type EventError struct { 18 | Time int64 `json:"time"` 19 | Event Event `json:"event"` 20 | ErrCode sdk.CodeType `json:"err_code"` 21 | } 22 | 23 | // EventExec is a function that can execute events. 24 | type EventExec = func(ctx sdk.Context, event Event) sdk.Error 25 | 26 | // BCEventErrReason - blockchain event error. deterministic. 27 | type BCEventErr struct { 28 | Time int64 `json:"time"` 29 | ErrCode sdk.CodeType `json:"err_code"` 30 | ErrCodeSpace sdk.CodespaceType `json:"err_code_space"` 31 | Reason string `json:"reason"` 32 | } 33 | 34 | func NewBCEventErr(ctx sdk.Context, err sdk.Error, reason string) BCEventErr { 35 | return BCEventErr{ 36 | Time: ctx.BlockTime().Unix(), 37 | ErrCode: err.Code(), 38 | ErrCodeSpace: err.Codespace(), 39 | Reason: reason, 40 | } 41 | } 42 | 43 | // BCEvent execute blockchain scheduled events. 44 | type BCEventExec = func(ctx sdk.Context) []BCEventErr 45 | -------------------------------------------------------------------------------- /x/reputation/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | types "github.com/lino-network/lino/x/reputation" 13 | ) 14 | 15 | func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: types.ModuleName, 18 | Short: "Querying commands for the reputation module", 19 | DisableFlagParsing: true, 20 | SuggestionsMinimumDistance: 2, 21 | RunE: client.ValidateCmd, 22 | } 23 | cmd.AddCommand(client.GetCommands( 24 | getCmdShow(cdc), 25 | )...) 26 | return cmd 27 | } 28 | 29 | // GetCmdShow - 30 | func getCmdShow(cdc *codec.Codec) *cobra.Command { 31 | return &cobra.Command{ 32 | Use: "show ", 33 | Short: "show ", 34 | Args: cobra.ExactArgs(1), 35 | RunE: func(cmd *cobra.Command, args []string) error { 36 | username := args[0] 37 | uri := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryReputation, username) 38 | rst := linotypes.MiniDollar{} 39 | return utils.CLIQueryJSONPrint(cdc, uri, nil, 40 | func() interface{} { return &rst }) 41 | }, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cmd/README.md: -------------------------------------------------------------------------------- 1 | # Lino Blockchain Command 2 | 3 | This cmd directory contains two command line tool: lino and linocli. _lino_ is used to luanch the Lino Blockchain node. _linocli_ can be used to interact with Lino Blockchain. 4 | 5 | # Launch Blockchain 6 | ## Generate genesis file 7 | ``` 8 | $ ./lino init 9 | ``` 10 | ## Start generate block as a validator 11 | ``` 12 | $ ./lino start 13 | ``` 14 | 15 | # Launch Client 16 | ## Transfer coin to a user 17 | ``` 18 | $ ./linocli transfer --sender= --receiver= --amount=1 --chain-id= --sequence= 19 | ``` 20 | 21 | ## Register an account 22 | ``` 23 | $ ./linocli register --referrer= --user= --amount=1 --chain-id= --sequence= 24 | ``` 25 | 26 | ## Follow & Unfollow 27 | Follow 28 | ``` 29 | $ ./linocli follow --follower= --followee= --is-follow=true --sequence= --chain-id= --sequence= 30 | ``` 31 | Unfollow 32 | ``` 33 | $ ./linocli follow --follower= --followee= --is-follow=false --sequence= --chain-id= --sequence= 34 | ``` 35 | ## Query Account 36 | Check Bank 37 | ``` 38 | $ ./linocli username XXXXXXXX 39 | ``` 40 | 41 | 42 | ## Others 43 | List all keys 44 | ``` 45 | $ ./linocli keys list 46 | ``` 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/core/coinday.md: -------------------------------------------------------------------------------- 1 | # CoinDay 2 | 3 | Borrowed the idea from Bitcoin code contributors and other researchers, CoinDay, on Lino Blockchain, is a number that measures how much LINO has been held for much time in an account. CoinDay is used to compute a user's allocated bandwidth and donation power. For example, if a user received 1 LINO on day 0 and 2 LINO on day 1, this user's CoinDay on day 2 is: 1 * 2(days) + 2 * 1(day). When someone transfers a certain amount of LINO to you, the CoinDay for that amount of LINO becomes 0 and starts to grow from the time you receive it. However, CoinDay cannot grow infinitely. There is a 7 days limit for any LINO's CoinDay to grow. The specific calculation is detailed bellow: 4 | 5 | When you receive LINO: 6 | The blockchain maintains a CoinDay DQueue to do Lazy Evaluation of your CoinDay. When you receive LINO, a new element will be appended to the queue, which contains the amount of LINO and the start time. Then, the blockchain will go over the queue and update your CoinDay. 7 | 8 | CoinDay = Sum(amount of LINO * min(current time - start time, 7 days)) 9 | 10 | When you transfer LINO to others: 11 | The newest elements in the CoinDay DQueue will be poped out and your CoinDay will be updated. 12 | 13 | When you donate LINO to content: 14 | The oldest elements in the CoinDay DQueue will be poped out and your CoinDay will be updated. 15 | -------------------------------------------------------------------------------- /x/price/querier.go: -------------------------------------------------------------------------------- 1 | package price 2 | 3 | import ( 4 | "strings" 5 | 6 | wire "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/price/types" 13 | ) 14 | 15 | // creates a querier for price REST endpoints 16 | func NewQuerier(pm PriceKeeper) sdk.Querier { 17 | cdc := wire.New() 18 | wire.RegisterCrypto(cdc) 19 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { 20 | switch path[0] { 21 | case types.QueryPriceCurrent: 22 | return utils.NewQueryResolver(0, func(args ...string) (interface{}, sdk.Error) { 23 | return pm.CurrPrice(ctx) 24 | })(ctx, cdc, path) 25 | case types.QueryPriceHistory: 26 | return utils.NewQueryResolver(0, func(args ...string) (interface{}, sdk.Error) { 27 | return pm.HistoryPrice(ctx), nil 28 | })(ctx, cdc, path) 29 | case types.QueryLastFeed: 30 | return utils.NewQueryResolver(1, func(args ...string) (interface{}, sdk.Error) { 31 | return pm.LastFeed(ctx, linotypes.AccountKey(args[0])) 32 | })(ctx, cdc, path) 33 | default: 34 | return nil, sdk.ErrUnknownRequest("unknown query endpoint:" + strings.Join(path, "/")) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /utils/cli.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client/context" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func CLIQueryJSONPrint(cdc *codec.Codec, uri string, data []byte, rstTypeFactory func() interface{}) error { 12 | cliCtx := context.NewCLIContext().WithCodec(cdc) 13 | 14 | res, _, err := cliCtx.QueryWithData(uri, data) 15 | if err != nil { 16 | fmt.Printf("Failed to Query and Print: %s, because %s", uri, err) 17 | return nil 18 | } 19 | 20 | rst := rstTypeFactory() 21 | cdc.MustUnmarshalJSON(res, rst) 22 | out, err := cdc.MarshalJSONIndent(rst, "", " ") 23 | if err != nil { 24 | return err 25 | } 26 | fmt.Println(string(out)) 27 | return nil 28 | } 29 | 30 | func SimpleQueryCmd(use, short, route, store string, nargs int, rstPointer interface{}) func(*codec.Codec) *cobra.Command { 31 | return func(cdc *codec.Codec) *cobra.Command { 32 | return &cobra.Command{ 33 | Use: use, 34 | Short: short, 35 | Args: cobra.ExactArgs(nargs), 36 | RunE: func(cmd *cobra.Command, args []string) error { 37 | uri := fmt.Sprintf("custom/%s/%s", route, store) 38 | for i := 0; i < nargs; i++ { 39 | uri += "/" + args[i] 40 | } 41 | return CLIQueryJSONPrint(cdc, uri, nil, 42 | func() interface{} { return rstPointer }) 43 | }, 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /x/validator/manager/hooks.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | linotypes "github.com/lino-network/lino/types" 7 | votemn "github.com/lino-network/lino/x/vote/manager" 8 | ) 9 | 10 | func (vm ValidatorManager) AfterAddingStake(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 11 | return vm.onStakeChange(ctx, username) 12 | } 13 | 14 | func (vm ValidatorManager) AfterSubtractingStake(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 15 | return vm.onStakeChange(ctx, username) 16 | } 17 | 18 | func (vm ValidatorManager) AfterSlashing(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 19 | return nil 20 | } 21 | 22 | type Hooks struct { 23 | vm ValidatorManager 24 | } 25 | 26 | var _ votemn.StakingHooks = Hooks{} 27 | 28 | // Return the wrapper struct 29 | func (vm ValidatorManager) Hooks() Hooks { 30 | return Hooks{vm} 31 | } 32 | 33 | func (h Hooks) AfterAddingStake(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 34 | return h.vm.AfterAddingStake(ctx, username) 35 | } 36 | 37 | func (h Hooks) AfterSubtractingStake(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 38 | return h.vm.AfterSubtractingStake(ctx, username) 39 | } 40 | 41 | func (h Hooks) AfterSlashing(ctx sdk.Context, username linotypes.AccountKey) sdk.Error { 42 | return h.vm.AfterSlashing(ctx, username) 43 | } 44 | -------------------------------------------------------------------------------- /x/reputation/repv2/encoder_test.go: -------------------------------------------------------------------------------- 1 | package repv2 2 | 3 | import ( 4 | // "fmt" 5 | // "math/big" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/suite" 9 | ) 10 | 11 | type EncoderTestSuite struct { 12 | suite.Suite 13 | } 14 | 15 | // func (suite *EncoderTestSuite) TestUserMeta() { 16 | // user := &userMeta{ 17 | // Consumption : big.NewInt() 18 | // Hold 19 | // Reputation 20 | // LastSettledRound 21 | // LastDonationRound 22 | // Unsettled 23 | 24 | // } 25 | // } 26 | 27 | // func BenchmarkEncoder(b *testing.B) { 28 | // user := &userMeta2{ 29 | // Consumption: Int{big.NewInt(10)}, 30 | // Hold: Int{big.NewInt(300)}, 31 | // Reputation: Int{big.NewInt(5000)}, 32 | // LastSettledRound: 3, 33 | // LastDonationRound: 5, 34 | // Unsettled: []Donation2{ 35 | // { 36 | // Pid: "1344", 37 | // Amount: Int{big.NewInt(3333)}, 38 | // Impact: Int{big.NewInt(55134)}, 39 | // }, 40 | // { 41 | // Pid: "1344", 42 | // Amount: Int{big.NewInt(3333)}, 43 | // Impact: Int{big.NewInt(55134)}, 44 | // }, 45 | // }, 46 | // } 47 | 48 | // sz := 0 49 | // for i := 0; i < b.N; i++ { 50 | // dt := encodeUserMeta2(user) 51 | // sz += len(dt) 52 | // _ = decodeUserMeta2(dt) 53 | // } 54 | 55 | // fmt.Println("xcx", sz) 56 | // } 57 | 58 | func TestEncoderTestSuite(t *testing.T) { 59 | suite.Run(t, new(EncoderTestSuite)) 60 | } 61 | -------------------------------------------------------------------------------- /x/price/types/msg_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/stretchr/testify/suite" 8 | 9 | "github.com/lino-network/lino/types" 10 | ) 11 | 12 | type PriceMsgTestSuite struct { 13 | suite.Suite 14 | } 15 | 16 | func TestPriceMsgTestSuite(t *testing.T) { 17 | suite.Run(t, new(PriceMsgTestSuite)) 18 | } 19 | 20 | func (suite *PriceMsgTestSuite) SetupTest() { 21 | } 22 | 23 | func (suite *PriceMsgTestSuite) TestFeedPriceMsgValidateBasic() { 24 | testCases := []struct { 25 | testName string 26 | msg FeedPriceMsg 27 | expectedResult sdk.Error 28 | }{ 29 | { 30 | "invalid username", 31 | FeedPriceMsg{ 32 | Username: "3v", 33 | Price: types.NewMiniDollar(100), 34 | }, 35 | types.ErrInvalidUsername("3v"), 36 | }, 37 | { 38 | "invalid price zero", 39 | FeedPriceMsg{ 40 | Username: "user1", 41 | Price: types.NewMiniDollar(0), 42 | }, 43 | ErrInvalidPriceFeed(types.NewMiniDollar(0)), 44 | }, 45 | { 46 | "invalid price negative", 47 | FeedPriceMsg{ 48 | Username: "user1", 49 | Price: types.NewMiniDollar(-100), 50 | }, 51 | ErrInvalidPriceFeed(types.NewMiniDollar(-100)), 52 | }, 53 | } 54 | 55 | for _, tc := range testCases { 56 | suite.Run(tc.testName, func() { 57 | result := tc.msg.ValidateBasic() 58 | suite.Equal(tc.expectedResult, result) 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /x/vote/model/ir.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | linotypes "github.com/lino-network/lino/types" 5 | "github.com/lino-network/lino/x/vote/types" 6 | ) 7 | 8 | // VoterIR - pk: username 9 | type VoterIR struct { 10 | Username linotypes.AccountKey `json:"username"` 11 | LinoStake linotypes.Coin `json:"lino_stake"` 12 | LastPowerChangeAt int64 `json:"last_power_change_at"` 13 | Interest linotypes.Coin `json:"interest"` 14 | Duty types.VoterDuty `json:"duty"` 15 | FrozenAmount linotypes.Coin `json:"frozen_amount"` 16 | } 17 | 18 | // LinoStakeStatIR - records the information needed by 19 | // lino power deposit, update and store daily. 20 | type LinoStakeStatIR struct { 21 | TotalConsumptionFriction linotypes.Coin `json:"total_consumption_friction"` 22 | UnclaimedFriction linotypes.Coin `json:"unclaimed_friction"` 23 | TotalLinoStake linotypes.Coin `json:"total_lino_power"` 24 | UnclaimedLinoStake linotypes.Coin `json:"unclaimed_lino_power"` 25 | } 26 | 27 | // StakeStatDayIR - stake stats of a day, pk: day 28 | type StakeStatDayIR struct { 29 | Day int64 `json:"day"` 30 | StakeStat LinoStakeStatIR `json:"stake_stat"` 31 | } 32 | 33 | // VoterTablesIR - state of voter 34 | type VoterTablesIR struct { 35 | Version int `json:"version"` 36 | Voters []VoterIR `json:"voters"` 37 | StakeStats []StakeStatDayIR `json:"stake_stats"` 38 | } 39 | -------------------------------------------------------------------------------- /x/price/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | linotypes "github.com/lino-network/lino/types" 9 | ) 10 | 11 | // ErrFedPriceNotFound - error when fed price is not found. 12 | func ErrFedPriceNotFound(u linotypes.AccountKey) sdk.Error { 13 | return linotypes.NewError( 14 | linotypes.CodeFedPriceNotFound, 15 | fmt.Sprintf("fed price of %v is not found", u)) 16 | } 17 | 18 | // ErrCurrentPriceNotFound - error current price is not found. 19 | func ErrCurrentPriceNotFound() sdk.Error { 20 | return linotypes.NewError( 21 | linotypes.CodeFedPriceNotFound, "current price not found") 22 | } 23 | 24 | // ErrNoValidator - error when no validator is found. 25 | func ErrNoValidator() sdk.Error { 26 | return linotypes.NewError( 27 | linotypes.CodeNoValidatorSet, fmt.Sprintf("no validator set found")) 28 | } 29 | 30 | // ErrNotAValidator - 31 | func ErrNotAValidator(u linotypes.AccountKey) sdk.Error { 32 | return linotypes.NewError( 33 | linotypes.CodeNotAValidator, fmt.Sprintf("%s is not a validator", u)) 34 | } 35 | 36 | // ErrInvalidPriceFeed - 37 | func ErrInvalidPriceFeed(price linotypes.MiniDollar) sdk.Error { 38 | return linotypes.NewError( 39 | linotypes.CodeInvalidPriceFeed, fmt.Sprintf("invalid price: %s", price)) 40 | } 41 | 42 | // ErrPriceFeedRateLimited - 43 | func ErrPriceFeedRateLimited() sdk.Error { 44 | return linotypes.NewError( 45 | linotypes.CodePriceFeedRateLimited, fmt.Sprintf("")) 46 | } 47 | -------------------------------------------------------------------------------- /types/minidollar.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "math/big" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // 1 LINO = 0.012 USD 10 | // 10^5 Coin = 12 * 10^7 MiniDollar 11 | // 1 coin = 1200 minidollar 12 | var TestnetPrice = NewMiniDollar(1200) 13 | 14 | // 1 MiniDollar = 10^(-10) USD. 15 | type MiniDollar struct { 16 | // embeding sdk.Int, inheriting marshal/unmarshal function from 17 | // sdk.Int, so DO NOT add any other field in this struct. 18 | sdk.Int 19 | } 20 | 21 | func NewMiniDollar(v int64) MiniDollar { 22 | return MiniDollar{sdk.NewInt(v)} 23 | } 24 | 25 | func NewMiniDollarFromInt(i sdk.Int) MiniDollar { 26 | return MiniDollar{i} 27 | } 28 | 29 | func NewMiniDollarFromBig(v *big.Int) MiniDollar { 30 | return MiniDollar{sdk.NewIntFromBigInt(v)} 31 | } 32 | 33 | // TODO(yumin): MUST DELETE on upgrade3 34 | func NewMiniDollarFromTestnetCoin(c Coin) MiniDollar { 35 | return NewMiniDollarFromInt(c.Amount.Mul(TestnetPrice.Int)) 36 | } 37 | 38 | func (m MiniDollar) Plus(other MiniDollar) MiniDollar { 39 | return MiniDollar{m.Add(other.Int)} 40 | } 41 | 42 | func (m MiniDollar) Minus(other MiniDollar) MiniDollar { 43 | return MiniDollar{m.Sub(other.Int)} 44 | } 45 | 46 | func (m MiniDollar) Multiply(other MiniDollar) MiniDollar { 47 | return MiniDollar{m.Mul(other.Int)} 48 | } 49 | 50 | func (m MiniDollar) Equal(other MiniDollar) bool { 51 | return m.Int.Equal(other.Int) 52 | } 53 | 54 | func (m MiniDollar) LT(other MiniDollar) bool { 55 | return m.Int.LT(other.Int) 56 | } 57 | -------------------------------------------------------------------------------- /docs/core/gov.md: -------------------------------------------------------------------------------- 1 | # Lock Point and Governance 2 | 3 | # Lock Point 4 | 5 | Based on the concept of DAO, the blockchain should under the control of all LINO holder. The LINO holder can participate the governance by lock LINO then become a voter. The voter has right to vote for proposal or become a validator. User can become voter to participate governance directly or delegate LINO to other voter. The proposals include content censorship, parameter change and code upgrade. Each proposal has 3 days for voting and validators are required to vote for parameter change and code upgrade proposal. The locked LINO holder can also share the reward daily from daily consumption. The reward will distribute to all locked LINO holder based on amount of LINO locked. If user revoke their locked LINO it will be pending money. 6 | 7 | ## Pending Money 8 | 9 | To prevent the malicious user spam the governance process and chain service, all governance behavior and chain service provider will need to lock LINO. When revoke, the locked LINO will be frozen and return to user separately. The times and interval for each frozen money listed as following: 10 | 11 | | Behavior | Return times | Return Interval (hour) | 12 | |------------------|:-------------:|------------------------:| 13 | | Developer revoke | 12 | 7*24 | 14 | | Validator revoke | 12 | 7*24 | 15 | | Unlock LINO | 12 | 7*24 | 16 | | Delegator revoke | 12 | 7*24 | -------------------------------------------------------------------------------- /x/vote/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | 10 | // linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/vote/model" 13 | types "github.com/lino-network/lino/x/vote/types" 14 | ) 15 | 16 | func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: "Querying commands for the vote module", 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | cmd.AddCommand(client.GetCommands( 25 | getCmdVoter(cdc), 26 | utils.SimpleQueryCmd( 27 | "stake-stats ", "stake-stats ", 28 | types.QuerierRoute, types.QueryStakeStats, 29 | 1, &model.LinoStakeStat{})(cdc), 30 | )...) 31 | return cmd 32 | } 33 | 34 | // GetCmdVoter - 35 | func getCmdVoter(cdc *codec.Codec) *cobra.Command { 36 | return &cobra.Command{ 37 | Use: "voter", 38 | Short: "voter [username]", 39 | Args: cobra.ExactArgs(1), 40 | RunE: func(cmd *cobra.Command, args []string) error { 41 | user := args[0] 42 | uri := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryVoter, user) 43 | rst := model.Voter{} 44 | return utils.CLIQueryJSONPrint(cdc, uri, nil, 45 | func() interface{} { return &rst }) 46 | }, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_even_distribution_with_remainder.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testapp-2", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testapp-2", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "0", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_distribute_according_to_consumption.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "1", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "2", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testapp-2", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testapp-2", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "4", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_even_distribution_with_remainder.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "1", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "1", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testapp-2", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testapp-2", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "1", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestMonthlyDistributeDevInflation/Success_distribute_according_to_consumption.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp-0", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp-0", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-1", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-1", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testapp-2", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testapp-2", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "0", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /x/developer/manager/input/TestDeveloperManagerSuite/TestIssueIDA.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-has-ida", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-has-ida", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "1", 42 | "key": "testapp-has-ida", 43 | "val": { 44 | "type": "lino/appida", 45 | "value": { 46 | "app": "testapp-has-ida", 47 | "name": "test-lemon", 48 | "price": "10000", 49 | "is_revoked": false, 50 | "revoke_coin_price": "0" 51 | } 52 | } 53 | }, 54 | { 55 | "prefix": "5", 56 | "key": "test2", 57 | "val": { 58 | "type": "lino/role", 59 | "value": { 60 | "aa": "test2" 61 | } 62 | } 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Lino Core Docs! 2 | 3 | Lino Network is a decentralized autonomous content community, where all means of production are self-governed by all members, ensuring all content value is directly distributed to content creators and affiliated contributors without going through a dominative middleman. 4 | 5 | In order to build an autonomous content community, a widely acknowledged protocol should be accepted and executed by the whole community in decentralized way. Any centralized behavior will lead to the conflict of interest between centralized service provider and content creator. 6 | 7 | Based on above assumption, we propose the Lino Core, which implements our autonomous centent community protocol based on user behaviors in decentralized way. It aims to support all related applications and accurately evaluates and rewards all contents and community contributors using the blockchain cryptocurrency: LINO. All value exchanges in the Lino community will occur through LINO and all user behaviors within the Lino community will be recorded and maintained by the Lino Blockchain. All behaviours are transparent and unmodified. 8 | 9 | ## Quick Start 10 | - [Consensus](./core/consensus.md) 11 | - [Account](./core/account.md) 12 | - [Authorization](./core/auth.md) 13 | - [Post](./core/post.md) 14 | - [Genesis](./core/genesis.md) 15 | - [Coin Day](./core/coinday.md) 16 | - [Inflation](./core/inflation.md) 17 | - [Reputation](./core/reputation.md) 18 | - [Evaluate of Content Value](./core/ecv.md) 19 | - [Lock Point and Governance](./core/gov.md) 20 | -------------------------------------------------------------------------------- /x/price/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/lino-network/lino/client" 9 | linotypes "github.com/lino-network/lino/types" 10 | "github.com/lino-network/lino/x/price/types" 11 | ) 12 | 13 | func GetTxCmd(cdc *codec.Codec) *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: types.ModuleName, 16 | Short: "Price tx subcommands", 17 | DisableFlagParsing: true, 18 | SuggestionsMinimumDistance: 2, 19 | RunE: client.ValidateCmd, 20 | } 21 | 22 | cmd.AddCommand(client.PostCommands( 23 | GetCmdFeedPrice(cdc), 24 | )...) 25 | 26 | return cmd 27 | } 28 | 29 | // GetCmdFeedPrice - feed price 30 | func GetCmdFeedPrice(cdc *codec.Codec) *cobra.Command { 31 | cmd := &cobra.Command{ 32 | Use: "feed ", 33 | Short: "feed ", 34 | Args: cobra.ExactArgs(2), 35 | RunE: func(cmd *cobra.Command, args []string) error { 36 | ctx := client.NewCoreContextFromViper().WithTxEncoder(linotypes.TxEncoder(cdc)) 37 | user := linotypes.AccountKey(args[0]) 38 | amount := args[1] 39 | amt, ok := sdk.NewIntFromString(amount) 40 | if !ok { 41 | panic("Invalid price") 42 | } 43 | 44 | msg := types.FeedPriceMsg{ 45 | Username: user, 46 | Price: linotypes.NewMiniDollarFromInt(amt), 47 | } 48 | return ctx.DoTxPrintResponse(msg) 49 | }, 50 | } 51 | return cmd 52 | } 53 | -------------------------------------------------------------------------------- /x/reputation/querier.go: -------------------------------------------------------------------------------- 1 | package reputation 2 | 3 | import ( 4 | wire "github.com/cosmos/cosmos-sdk/codec" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | "github.com/lino-network/lino/types" 7 | abci "github.com/tendermint/tendermint/abci/types" 8 | ) 9 | 10 | const ( 11 | // ModuleKey is the name of the module 12 | ModuleName = "reputation" 13 | 14 | // RouterKey is the message route for gov 15 | RouterKey = ModuleName 16 | 17 | // QuerierRoute is the querier route for gov 18 | QuerierRoute = ModuleName 19 | 20 | QueryReputation = "rep" 21 | ) 22 | 23 | // creates a querier for vote REST endpoints 24 | func NewQuerier(rm ReputationKeeper) sdk.Querier { 25 | cdc := wire.New() 26 | wire.RegisterCrypto(cdc) 27 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { 28 | switch path[0] { 29 | case QueryReputation: 30 | return queryReputation(ctx, cdc, path[1:], req, rm) 31 | default: 32 | return nil, sdk.ErrUnknownRequest("unknown reputation query endpoint") 33 | } 34 | } 35 | } 36 | 37 | func queryReputation(ctx sdk.Context, cdc *wire.Codec, path []string, req abci.RequestQuery, rm ReputationKeeper) ([]byte, sdk.Error) { 38 | if err := types.CheckPathContentAndMinLength(path, 1); err != nil { 39 | return nil, err 40 | } 41 | reputation, err := rm.GetReputation(ctx, types.AccountKey(path[0])) 42 | if err != nil { 43 | return nil, err 44 | } 45 | res, marshalErr := cdc.MarshalJSON(reputation) 46 | if marshalErr != nil { 47 | return nil, ErrQueryFailed() 48 | } 49 | return res, nil 50 | } 51 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestIssueIDA/Fail_Developer_doesnt_exist.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-has-ida", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-has-ida", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "1", 42 | "key": "testapp-has-ida", 43 | "val": { 44 | "type": "lino/appida", 45 | "value": { 46 | "app": "testapp-has-ida", 47 | "name": "test-lemon", 48 | "price": "10000", 49 | "is_revoked": false, 50 | "revoke_coin_price": "0" 51 | } 52 | } 53 | }, 54 | { 55 | "prefix": "5", 56 | "key": "test2", 57 | "val": { 58 | "type": "lino/role", 59 | "value": { 60 | "aa": "test2" 61 | } 62 | } 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestIssueIDA/Fail_Developer_has_already_issued_IDA.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-has-ida", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-has-ida", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "1", 42 | "key": "testapp-has-ida", 43 | "val": { 44 | "type": "lino/appida", 45 | "value": { 46 | "app": "testapp-has-ida", 47 | "name": "test-lemon", 48 | "price": "10000", 49 | "is_revoked": false, 50 | "revoke_coin_price": "0" 51 | } 52 | } 53 | }, 54 | { 55 | "prefix": "5", 56 | "key": "test2", 57 | "val": { 58 | "type": "lino/role", 59 | "value": { 60 | "aa": "test2" 61 | } 62 | } 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /x/post/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/post/model" 13 | "github.com/lino-network/lino/x/post/types" 14 | ) 15 | 16 | func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: "Querying commands for the post module", 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | cmd.AddCommand(client.GetCommands( 25 | getCmdInfo(cdc), 26 | utils.SimpleQueryCmd( 27 | "cw", 28 | "cw prints the consumption competition metadata, unit: miniDollar", 29 | types.QuerierRoute, types.QueryConsumptionWindow, 0, &linotypes.MiniDollar{})(cdc), 30 | )...) 31 | return cmd 32 | } 33 | 34 | // GetCmdInfo - 35 | func getCmdInfo(cdc *codec.Codec) *cobra.Command { 36 | return &cobra.Command{ 37 | Use: "info ", 38 | Short: "info ", 39 | Args: cobra.ExactArgs(1), 40 | RunE: func(cmd *cobra.Command, args []string) error { 41 | permlink := args[0] 42 | uri := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryPostInfo, permlink) 43 | rst := model.Post{} 44 | return utils.CLIQueryJSONPrint(cdc, uri, nil, 45 | func() interface{} { return &rst }) 46 | }, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /x/post/keeper.go: -------------------------------------------------------------------------------- 1 | package post 2 | 3 | //go:generate mockery -name PostKeeper 4 | 5 | import ( 6 | codec "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | linotypes "github.com/lino-network/lino/types" 10 | "github.com/lino-network/lino/x/post/manager" 11 | "github.com/lino-network/lino/x/post/model" 12 | "github.com/lino-network/lino/x/post/types" 13 | ) 14 | 15 | type PostKeeper interface { 16 | DoesPostExist(ctx sdk.Context, permlink linotypes.Permlink) bool 17 | GetPost(ctx sdk.Context, permlink linotypes.Permlink) (model.Post, sdk.Error) 18 | CreatePost(ctx sdk.Context, author linotypes.AccountKey, postID string, createdBy linotypes.AccountKey, content string, title string) sdk.Error 19 | UpdatePost(ctx sdk.Context, author linotypes.AccountKey, postID, title, content string) sdk.Error 20 | DeletePost(ctx sdk.Context, permlink linotypes.Permlink) sdk.Error 21 | LinoDonate(ctx sdk.Context, from linotypes.AccountKey, amount linotypes.Coin, author linotypes.AccountKey, postID string, app linotypes.AccountKey) sdk.Error 22 | IDADonate(ctx sdk.Context, from linotypes.AccountKey, n linotypes.MiniIDA, author linotypes.AccountKey, postID string, app, signer linotypes.AccountKey) sdk.Error 23 | ExecRewardEvent(ctx sdk.Context, reward types.RewardEvent) sdk.Error 24 | 25 | // querier 26 | GetComsumptionWindow(ctx sdk.Context) linotypes.MiniDollar 27 | 28 | ImportFromFile(ctx sdk.Context, cdc *codec.Codec, filepath string) error 29 | ExportToFile(ctx sdk.Context, cdc *codec.Codec, filepath string) error 30 | } 31 | 32 | var _ PostKeeper = manager.PostManager{} 33 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestUpdatePriceSlash/testnet_no_slash.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "1200", 10 | "update_at": "0" 11 | }, 12 | { 13 | "price": "1200", 14 | "update_at": "3600" 15 | }, 16 | { 17 | "price": "1200", 18 | "update_at": "7200" 19 | }, 20 | { 21 | "price": "1200", 22 | "update_at": "10800" 23 | } 24 | ] 25 | } 26 | }, 27 | { 28 | "prefix": "2", 29 | "key": "", 30 | "val": { 31 | "type": "lino/price/current", 32 | "value": { 33 | "price": "1200", 34 | "update_at": "7200" 35 | } 36 | } 37 | }, 38 | { 39 | "prefix": "3", 40 | "key": "", 41 | "val": { 42 | "type": "lino/price/lastvals", 43 | "value": [ 44 | "val1", 45 | "val2", 46 | "val3" 47 | ] 48 | } 49 | }, 50 | { 51 | "prefix": "4", 52 | "key": "", 53 | "val": { 54 | "type": "lino/price/feedhistory", 55 | "value": [ 56 | { 57 | "price": "1200", 58 | "feeded": null, 59 | "update_at": "3600" 60 | }, 61 | { 62 | "price": "1200", 63 | "feeded": null, 64 | "update_at": "7200" 65 | }, 66 | { 67 | "price": "1200", 68 | "feeded": null, 69 | "update_at": "10800" 70 | } 71 | ] 72 | } 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /docs/changelog/upgrade2-ida.md: -------------------------------------------------------------------------------- 1 | # In-app Digital Assets 2 | 3 | ## Concept 4 | --- 5 | **MiniDollar**: Introduce types.MiniDollar as the unit of consensus 6 | price of Lino. One MiniDollar is 10^(-8) USD. Internally it is a sdk.Int. 7 | 8 | **MiniIDA**: Introduce types.MiniIDA as the unit of IDA. One MiniIDA = 10^5 IDA. 9 | 10 | ## Changes to Post 11 | --- 12 | 13 | 1. Simplify post struct, remove unused fields. 14 | 2. Remove view/upvote/report tx. 15 | 3. Storage use MustUnmarshalBinaryLengthPrefixed, same as cosmos modules. 16 | 17 | ## Changes to Developer 18 | --- 19 | 20 | 1. Deposit from Upgrade1 will be burned, since In Upgrade2 Developer uses stake-in. 21 | 2. One account can only be a developer once. Had the account unregistered, cannot register again. 22 | 3. Remove DeveloperList. Replace it with GetActiveDeveloper() which returns all active developers. 23 | 24 | ### Minors 25 | 26 | 1. experimental refactor on post structure. 27 | 28 | ## Changes to Donation 29 | --- 30 | 31 | 1. Reputation use MiniDollar as the unit. For users before upgrade2, 32 | reputation scores are converted to minidollar. 33 | 2. Impact Factor(also called donation power) use MiniDollar as unit as well. 34 | 3. Consumption window use MiniDollar. 35 | 4. still support donating using LINO. 36 | 37 | ## BREAKING 38 | --- 39 | 40 | **CreatePostMsg**: two new fields: signer, createdBy. Both must be provided. 41 | **Codec**: post signbytes are now sorted by sdk.MustSortJSON. 42 | **links**: now are in content. 43 | **CreateAffiliateAccounts**: app need to create affilicate accounts to create posts. 44 | **DeveloperRegisterMsg**: temporarily disabled as vote module is not ready. 45 | -------------------------------------------------------------------------------- /x/reputation/repv2/encoder.go: -------------------------------------------------------------------------------- 1 | //nolint:unconvert 2 | package repv2 3 | 4 | import ( 5 | wire "github.com/cosmos/cosmos-sdk/codec" 6 | ) 7 | 8 | var cdc = wire.New() 9 | 10 | func decodeUserMeta(data []byte) *userMeta { 11 | if data == nil { 12 | return nil 13 | } 14 | rst := &userMeta{} 15 | cdc.MustUnmarshalBinaryBare(data, rst) 16 | return rst 17 | } 18 | 19 | func encodeUserMeta(dt *userMeta) []byte { 20 | if dt == nil { 21 | return nil 22 | } 23 | rst := cdc.MustMarshalBinaryBare(dt) 24 | return []byte(rst) 25 | } 26 | 27 | func decodeRoundMeta(data []byte) *roundMeta { 28 | if data == nil { 29 | return nil 30 | } 31 | rst := &roundMeta{} 32 | cdc.MustUnmarshalBinaryBare(data, rst) 33 | return rst 34 | } 35 | 36 | func encodeRoundMeta(dt *roundMeta) []byte { 37 | if dt == nil { 38 | return nil 39 | } 40 | rst := cdc.MustMarshalBinaryBare(dt) 41 | return []byte(rst) 42 | } 43 | 44 | func decodeRoundPostMeta(data []byte) *roundPostMeta { 45 | if data == nil { 46 | return nil 47 | } 48 | rst := &roundPostMeta{} 49 | cdc.MustUnmarshalBinaryBare(data, rst) 50 | return rst 51 | } 52 | 53 | func encodeRoundPostMeta(dt *roundPostMeta) []byte { 54 | if dt == nil { 55 | return nil 56 | } 57 | rst := cdc.MustMarshalBinaryBare(dt) 58 | return []byte(rst) 59 | } 60 | 61 | func decodeGameMeta(data []byte) *gameMeta { 62 | if data == nil { 63 | return nil 64 | } 65 | rst := &gameMeta{} 66 | cdc.MustUnmarshalBinaryBare(data, rst) 67 | return rst 68 | } 69 | 70 | func encodeGameMeta(dt *gameMeta) []byte { 71 | if dt == nil { 72 | return nil 73 | } 74 | rst := cdc.MustMarshalBinaryBare(dt) 75 | return []byte(rst) 76 | } 77 | -------------------------------------------------------------------------------- /x/price/keeper.go: -------------------------------------------------------------------------------- 1 | package price 2 | 3 | //go:generate mockery -name PriceKeeper 4 | 5 | import ( 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | linotypes "github.com/lino-network/lino/types" 9 | "github.com/lino-network/lino/x/price/model" 10 | ) 11 | 12 | // PriceKeeper - conversion between Coin/MiniDollar at current consensus price. 13 | type PriceKeeper interface { 14 | // set initial price of LINO 15 | InitGenesis(ctx sdk.Context, initPrice linotypes.MiniDollar) sdk.Error 16 | 17 | // feed price. 18 | FeedPrice(ctx sdk.Context, validator linotypes.AccountKey, price linotypes.MiniDollar) sdk.Error 19 | 20 | // UpdatePrice is the hourly event. 21 | UpdatePrice(ctx sdk.Context) sdk.Error 22 | 23 | // CoinToMiniDollar - convert minidollar to coin 24 | // since internally, every coin have a price of minidollar, so any amount of coin 25 | // can all be converted into minidollar. 26 | CoinToMiniDollar(ctx sdk.Context, coin linotypes.Coin) (bought linotypes.MiniDollar, err sdk.Error) 27 | 28 | // MiniDollarToCoin - return the maximum coins that @p dollar can buy and 29 | // the amount of dollar used. The returned value is a pair of (new token, used previous token). 30 | // As there is a minimum price of coin, for dollars that are less than price of one coin 31 | // they are not used. 32 | MiniDollarToCoin(ctx sdk.Context, dollar linotypes.MiniDollar) (bought linotypes.Coin, used linotypes.MiniDollar, err sdk.Error) 33 | 34 | // Getters 35 | CurrPrice(ctx sdk.Context) (linotypes.MiniDollar, sdk.Error) 36 | HistoryPrice(ctx sdk.Context) []model.FeedHistory 37 | LastFeed(ctx sdk.Context, validator linotypes.AccountKey) (*model.FedPrice, sdk.Error) 38 | } 39 | -------------------------------------------------------------------------------- /x/vote/querier.go: -------------------------------------------------------------------------------- 1 | package vote 2 | 3 | import ( 4 | "strconv" 5 | 6 | wire "github.com/cosmos/cosmos-sdk/codec" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | abci "github.com/tendermint/tendermint/abci/types" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/vote/types" 13 | ) 14 | 15 | // creates a querier for vote REST endpoints 16 | func NewQuerier(vk VoteKeeper) sdk.Querier { 17 | cdc := wire.New() 18 | wire.RegisterCrypto(cdc) 19 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { 20 | switch path[0] { 21 | case types.QueryVoter: 22 | return queryVoter(ctx, cdc, path[1:], req, vk) 23 | case types.QueryStakeStats: 24 | return utils.NewQueryResolver(1, func(args ...string) (interface{}, sdk.Error) { 25 | day, err := strconv.ParseInt(args[0], 10, 64) 26 | if err != nil { 27 | return nil, linotypes.ErrInvalidQueryPath() 28 | } 29 | return vk.GetStakeStatsOfDay(ctx, day) 30 | })(ctx, cdc, path) 31 | default: 32 | return nil, sdk.ErrUnknownRequest("unknown vote query endpoint") 33 | } 34 | } 35 | } 36 | 37 | func queryVoter(ctx sdk.Context, cdc *wire.Codec, path []string, req abci.RequestQuery, vk VoteKeeper) ([]byte, sdk.Error) { 38 | if err := linotypes.CheckPathContentAndMinLength(path, 1); err != nil { 39 | return nil, err 40 | } 41 | voter, err := vk.GetVoter(ctx, linotypes.AccountKey(path[0])) 42 | if err != nil { 43 | return nil, err 44 | } 45 | res, marshalErr := cdc.MarshalJSON(voter) 46 | if marshalErr != nil { 47 | return nil, types.ErrQueryFailed() 48 | } 49 | return res, nil 50 | } 51 | -------------------------------------------------------------------------------- /docs/core/ecv.md: -------------------------------------------------------------------------------- 1 | # Evaluate of Content Value 2 | 3 | To get bonus from content creator inflation pool, the content creator need to publish post then get donation. The donation will subtract the coin with most charged coin day first. The coin day consumed will be the input of reputation system, after that a donation power will be calculated and as the input to the Evaluate of Content value. Evaluated result then will be added to a seven-days window. After 7 days, get content bonus and send to content author. Evaluate of Content Value result: 4 | ``` 5 | r = A * K * κ * τ * η 6 | ``` 7 | where A is the donation power; K is the adjustment of cumulative consumption amount on the content; κ is the consumption amount adjustment; τ is the consumption time adjustment, and η is the adjustment according to the number of times of consumption of the same content creator. 8 | ``` 9 | K = 1 + 1/(1+e ^(c/1000−5)) 10 | ``` 11 | Where c is the total consumption amount on the content. 12 | ``` 13 | κ = (A)^-0.2 14 | ``` 15 | 16 | ``` 17 | τ = 1/(1+e^(Δt/3153600−5)) 18 | ``` 19 | 20 | Where Δt (in seconds) is the consumption time minus content creation time. 21 | 22 | ``` 23 | η = 1 + 1/(1+e^(n−7)) 24 | ``` 25 | 26 | Where n is the number of times of consumptions of the same content creator. 27 | 28 | After the evaluate result added to the window, after 7 days, this evaluate result will be pop from the window and get the portion of inflation from the content creator inflation pool. The equation: 29 | ``` 30 | reward = (r/w)*p 31 | ``` 32 | Where w is total amount in seven-days window and p is the penalty score. The penalty score is calculated as: 33 | ``` 34 | p = 1 - min(report/upvote, 1) 35 | ``` 36 | -------------------------------------------------------------------------------- /x/auth/errors.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/lino-network/lino/types" 8 | ) 9 | 10 | // ErrIncorrectStdTxType - error if parse std tx failed 11 | func ErrIncorrectStdTxType() sdk.Error { 12 | return types.NewError(types.CodeIncorrectStdTxType, fmt.Sprint("incorrect stdTx type")) 13 | } 14 | 15 | // ErrNoSignatures - error if transaction without signatures 16 | func ErrNoSignatures() sdk.Error { 17 | return types.NewError(types.CodeNoSignatures, fmt.Sprint("no signatures")) 18 | } 19 | 20 | // ErrUnknownMsgType - error if msg can't be recognized 21 | func ErrUnknownMsgType() sdk.Error { 22 | return types.NewError(types.CodeUnknownMsgType, fmt.Sprint("unknown msg type")) 23 | } 24 | 25 | // ErrWrongNumberOfSigners - error if number of signers and signatures mismatch 26 | func ErrWrongNumberOfSigners() sdk.Error { 27 | return types.NewError(types.CodeWrongNumberOfSigners, fmt.Sprint("the number of siners is wrong")) 28 | } 29 | 30 | // XXX(yumin): no longer available, due to upgrade-1. 31 | // ErrInvalidSequence - error if sequence number mismatch 32 | // func ErrInvalidSequence(msg string) sdk.Error { 33 | // return types.NewError(types.CodeInvalidSequence, fmt.Sprintf("msg: %v", msg)) 34 | // } 35 | 36 | // ErrUnverifiedBytes - error if signbyte verification failed 37 | func ErrUnverifiedBytes(msg string) sdk.Error { 38 | return types.NewError(types.CodeUnverifiedBytes, fmt.Sprintf("msg: %v", msg)) 39 | } 40 | 41 | // ErrMsgFeeNotEnough - error if the provided message fee is not enough 42 | func ErrMsgFeeNotEnough() sdk.Error { 43 | return types.NewError(types.CodeMsgFeeNotEnough, fmt.Sprint("message fee is not enough")) 44 | } 45 | -------------------------------------------------------------------------------- /x/developer/model/developer.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | types "github.com/lino-network/lino/types" 5 | ) 6 | 7 | // Developer - developer is account with developer deposit, can get developer inflation 8 | type Developer struct { 9 | Username types.AccountKey `json:"username"` 10 | // Deprecated field, use stakein amount as requirement since upgrade2. 11 | Deposit types.Coin `json:"deposit"` 12 | AppConsumption types.MiniDollar `json:"app_consumption"` 13 | Website string `json:"web_site"` 14 | Description string `json:"description"` 15 | AppMetaData string `json:"app_meta_data"` 16 | IsDeleted bool `json:"is_deleted"` 17 | NAffiliated int64 `json:"n_affiliated"` 18 | } 19 | 20 | // AppIDA - app issued IDA. 21 | type AppIDA struct { 22 | App types.AccountKey `json:"app"` 23 | Name string `json:"name"` 24 | MiniIDAPrice types.MiniDollar `json:"price"` 25 | IsRevoked bool `json:"is_revoked"` 26 | RevokeCoinPrice types.MiniDollar `json:"revoke_coin_price"` // the price of one coin upon revoke. 27 | } 28 | 29 | // AppIDAStats - app ida stats 30 | type AppIDAStats struct { 31 | Total types.MiniDollar `json:"total"` 32 | } 33 | 34 | // Role - User Role 35 | type Role struct { 36 | AffiliatedApp types.AccountKey `json:"aa"` 37 | } 38 | 39 | // IDABank - IDA's bank 40 | type IDABank struct { 41 | Balance types.MiniDollar `json:"b"` 42 | Unauthed bool `json:"unauthed,omitempty"` 43 | } 44 | 45 | type ReservePool struct { 46 | Total types.Coin `json:"total"` 47 | TotalMiniDollar types.MiniDollar `json:"total_minidollar"` 48 | } 49 | -------------------------------------------------------------------------------- /test/post/donation_test.go: -------------------------------------------------------------------------------- 1 | package post 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/lino-network/lino/test" 8 | "github.com/lino-network/lino/types" 9 | 10 | // acc "github.com/lino-network/lino/x/account" 11 | post "github.com/lino-network/lino/x/post/types" 12 | "github.com/tendermint/tendermint/crypto/secp256k1" 13 | ) 14 | 15 | // test donate to a normal post 16 | func TestNormalDonation(t *testing.T) { 17 | newPostUserTransactionPriv := secp256k1.GenPrivKey() 18 | newPostUser := "poster" 19 | postID := "New Post" 20 | 21 | newDonateUserTransactionPriv := secp256k1.GenPrivKey() 22 | newDonateUser := "donator" 23 | baseT := time.Unix(0, 0).Add(3600 * time.Second) 24 | baseTime := baseT.Unix() 25 | lb := test.NewTestLinoBlockchain(t, test.DefaultNumOfVal, baseT) 26 | 27 | test.CreateAccount(t, newPostUser, lb, 0, 28 | secp256k1.GenPrivKey(), newPostUserTransactionPriv, "100") 29 | test.CreateAccount(t, newDonateUser, lb, 1, 30 | secp256k1.GenPrivKey(), newDonateUserTransactionPriv, "100") 31 | 32 | test.CreateTestPost( 33 | t, lb, newPostUser, postID, 1, newPostUserTransactionPriv, baseTime) 34 | 35 | test.CheckBalance(t, newPostUser, lb, types.NewCoinFromInt64(99*types.Decimals)) 36 | test.CheckBalance(t, newDonateUser, lb, types.NewCoinFromInt64(99*types.Decimals)) 37 | 38 | donateMsg := post.NewDonateMsg( 39 | newDonateUser, types.LNO("50"), newPostUser, postID, "", "") 40 | 41 | test.SignCheckDeliver(t, lb, donateMsg, 1, true, newDonateUserTransactionPriv, baseTime) 42 | 43 | test.CheckBalance(t, newDonateUser, lb, types.NewCoinFromInt64(49*types.Decimals)) 44 | test.CheckBalance(t, newPostUser, lb, types.NewCoinFromInt64(9900000+4505000)) // 90.1% * 50 45 | } 46 | -------------------------------------------------------------------------------- /x/price/manager/golden/TestPriceManagerSuite/TestUpdatePriceCurrPrice/initial_price_is_kept_no_feed.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/history", 7 | "value": [ 8 | { 9 | "price": "1200", 10 | "update_at": "0" 11 | }, 12 | { 13 | "price": "1200", 14 | "update_at": "3600" 15 | }, 16 | { 17 | "price": "1200", 18 | "update_at": "7200" 19 | }, 20 | { 21 | "price": "1200", 22 | "update_at": "10800" 23 | } 24 | ] 25 | } 26 | }, 27 | { 28 | "prefix": "2", 29 | "key": "", 30 | "val": { 31 | "type": "lino/price/current", 32 | "value": { 33 | "price": "1200", 34 | "update_at": "7200" 35 | } 36 | } 37 | }, 38 | { 39 | "prefix": "3", 40 | "key": "", 41 | "val": { 42 | "type": "lino/price/lastvals", 43 | "value": [ 44 | "val1", 45 | "val2", 46 | "val3", 47 | "val4", 48 | "val5", 49 | "val6", 50 | "val7" 51 | ] 52 | } 53 | }, 54 | { 55 | "prefix": "4", 56 | "key": "", 57 | "val": { 58 | "type": "lino/price/feedhistory", 59 | "value": [ 60 | { 61 | "price": "1200", 62 | "feeded": null, 63 | "update_at": "3600" 64 | }, 65 | { 66 | "price": "1200", 67 | "feeded": null, 68 | "update_at": "7200" 69 | }, 70 | { 71 | "price": "1200", 72 | "feeded": null, 73 | "update_at": "10800" 74 | } 75 | ] 76 | } 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /x/developer/manager/golden/TestDeveloperManagerSuite/TestUpdateAffiliated/Success_deactivate.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-max-affiliated", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-max-affliated", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "500" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testuser-developer", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testuser-developer", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "0", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | }, 59 | { 60 | "prefix": "5", 61 | "key": "testuser-affiliated", 62 | "val": { 63 | "type": "lino/role", 64 | "value": { 65 | "aa": "testapp-a" 66 | } 67 | } 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /types/common_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/tendermint/tendermint/crypto/secp256k1" 8 | ) 9 | 10 | func TestIsUsername(t *testing.T) { 11 | testCases := map[string]struct { 12 | accountKeys []AccountKey 13 | expectRes bool 14 | }{ 15 | "username is too short": { 16 | accountKeys: []AccountKey{"us"}, 17 | expectRes: false, 18 | }, 19 | "username is too long": { 20 | accountKeys: []AccountKey{"useruseruseruseruseru"}, 21 | expectRes: false, 22 | }, 23 | "invalid characters": { 24 | accountKeys: []AccountKey{"register#", "_register", "-register", "reg@ister", "re--gister", 25 | "reg*ister", "register!", "register()", "reg$ister", "reg ister", " register", "re_-gister", 26 | "reg=ister", "register^", "register.", "reg$ister,", "Register", "r__egister", "reGister", 27 | "r_--gister", "re.-gister", ".re-gister", "re-gister.", "register_", "register-", "a.2.2.-.-..2", 28 | ".register", "register..", "_.register", "123123", "reg--ster", "reg$ster", "re%gister", "regist\"er", 29 | "reg?ster", "reg:ster", "register", "reg{ster", "regi}ster", "reg'ster", "reg`ster"}, 30 | expectRes: false, 31 | }, 32 | "address": { 33 | accountKeys: []AccountKey{AccountKey(secp256k1.GenPrivKey().PubKey().Address())}, 34 | expectRes: false, 35 | }, 36 | "valid username": { 37 | accountKeys: []AccountKey{"register", "re.gister", "re-gister", "reg", "registerregisterregi"}, 38 | expectRes: true, 39 | }, 40 | } 41 | 42 | for testName, tc := range testCases { 43 | for _, accKey := range tc.accountKeys { 44 | res := accKey.IsValid() 45 | assert.Equal(t, tc.expectRes, res, "%s", testName) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /x/price/types/msg.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | "github.com/lino-network/lino/types" 9 | ) 10 | 11 | // FeedPriceMsg - Validastors need to send this message to feed price. 12 | type FeedPriceMsg struct { 13 | Username types.AccountKey `json:"username"` 14 | Price types.MiniDollar `json:"price"` 15 | } 16 | 17 | var _ types.Msg = FeedPriceMsg{} 18 | 19 | // Route - implements sdk.Msg 20 | func (msg FeedPriceMsg) Route() string { return RouterKey } 21 | 22 | // Type - implements sdk.Msg 23 | func (msg FeedPriceMsg) Type() string { return "FeedPriceMsg" } 24 | 25 | // ValidateBasic - implements sdk.Msg 26 | func (msg FeedPriceMsg) ValidateBasic() sdk.Error { 27 | if !msg.Username.IsValid() { 28 | return types.ErrInvalidUsername(msg.Username) 29 | } 30 | if !msg.Price.IsPositive() { 31 | return ErrInvalidPriceFeed(msg.Price) 32 | } 33 | return nil 34 | } 35 | 36 | func (msg FeedPriceMsg) String() string { 37 | return fmt.Sprintf("FeedPriceMsg{%s, %s}", msg.Username, msg.Price) 38 | } 39 | 40 | func (msg FeedPriceMsg) GetPermission() types.Permission { 41 | return types.TransactionPermission 42 | } 43 | 44 | // GetSignBytes - implements sdk.Msg 45 | func (msg FeedPriceMsg) GetSignBytes() []byte { 46 | return getSignBytes(msg) 47 | } 48 | 49 | // GetSigners - implements sdk.Msg 50 | func (msg FeedPriceMsg) GetSigners() []sdk.AccAddress { 51 | return []sdk.AccAddress{sdk.AccAddress(msg.Username)} 52 | } 53 | 54 | // GetConsumeAmount - implements types.Msg 55 | func (msg FeedPriceMsg) GetConsumeAmount() types.Coin { 56 | return types.NewCoinFromInt64(0) 57 | } 58 | 59 | // utils 60 | func getSignBytes(msg sdk.Msg) []byte { 61 | return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg)) 62 | } 63 | -------------------------------------------------------------------------------- /test/account/recover_test.go: -------------------------------------------------------------------------------- 1 | package account 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/lino-network/lino/test" 8 | "github.com/lino-network/lino/types" 9 | accmodel "github.com/lino-network/lino/x/account/model" 10 | acctypes "github.com/lino-network/lino/x/account/types" 11 | 12 | sdk "github.com/cosmos/cosmos-sdk/types" 13 | "github.com/tendermint/tendermint/crypto/secp256k1" 14 | ) 15 | 16 | func TestRecoverAccount(t *testing.T) { 17 | transactionPriv := secp256k1.GenPrivKey() 18 | signingPriv := secp256k1.GenPrivKey() 19 | newTransactionPriv := secp256k1.GenPrivKey() 20 | newSigningPriv := secp256k1.GenPrivKey() 21 | newAccountName := "newuser" 22 | 23 | baseT := time.Unix(0, 0) 24 | baseTime := baseT.Unix() 25 | lb := test.NewTestLinoBlockchain(t, test.DefaultNumOfVal, baseT) 26 | 27 | registerMsgV2 := acctypes.NewRegisterV2Msg( 28 | types.NewAccOrAddrFromAcc( 29 | types.AccountKey(test.GenesisUser)), newAccountName, types.LNO("100"), 30 | transactionPriv.PubKey(), signingPriv.PubKey()) 31 | test.SignCheckDeliverWithMultiSig( 32 | t, lb, registerMsgV2, []uint64{0, 0}, true, 33 | []secp256k1.PrivKeySecp256k1{test.GenesisTransactionPriv, transactionPriv}, baseTime) 34 | 35 | recoverMsg := acctypes.NewRecoverMsg(newAccountName, newTransactionPriv.PubKey(), newSigningPriv.PubKey()) 36 | test.SignCheckDeliverWithMultiSig( 37 | t, lb, recoverMsg, []uint64{1, 0}, true, 38 | []secp256k1.PrivKeySecp256k1{transactionPriv, newTransactionPriv}, baseTime) 39 | test.CheckAccountInfo(t, newAccountName, lb, accmodel.AccountInfo{ 40 | Username: types.AccountKey(newAccountName), 41 | TransactionKey: newTransactionPriv.PubKey(), 42 | SigningKey: newSigningPriv.PubKey(), 43 | CreatedAt: baseTime, 44 | Address: sdk.AccAddress(newTransactionPriv.PubKey().Address()), 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /x/account/manager/event.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | linotypes "github.com/lino-network/lino/types" 7 | ) 8 | 9 | // ReturnCoinEvent - return a certain amount of coin to an account 10 | type ReturnCoinEvent struct { 11 | Username linotypes.AccountKey `json:"username"` 12 | Amount linotypes.Coin `json:"amount"` 13 | ReturnType linotypes.TransferDetailType `json:"return_type"` 14 | FromPool linotypes.PoolName `json:"from_pool"` 15 | At int64 `json:"at"` 16 | } 17 | 18 | // Execute - execute coin return events 19 | func (event ReturnCoinEvent) Execute(ctx sdk.Context, am AccountManager) sdk.Error { 20 | err := am.AddPending(ctx, event.Username, event.Amount.Neg()) 21 | if err != nil { 22 | return err 23 | } 24 | return am.MoveFromPool( 25 | ctx, event.FromPool, linotypes.NewAccOrAddrFromAcc(event.Username), event.Amount) 26 | } 27 | 28 | // CreateCoinReturnEvents - create coin return events 29 | // The return interval list is expected to be executed at [start + interval, start + 2 * interval...] 30 | // If [start, start + interval...] is expected, pass int (startAt - interval) as start at instead. 31 | func CreateCoinReturnEvents(username linotypes.AccountKey, startAt, interval, times int64, coin linotypes.Coin, returnType linotypes.TransferDetailType, pool linotypes.PoolName) []ReturnCoinEvent { 32 | events := []ReturnCoinEvent{} 33 | for i := int64(0); i < times; i++ { 34 | pieceDec := coin.ToDec().Quo(sdk.NewDec(times - i)) 35 | piece := linotypes.DecToCoin(pieceDec) 36 | coin = coin.Minus(piece) 37 | 38 | event := ReturnCoinEvent{ 39 | Username: username, 40 | Amount: piece, 41 | ReturnType: returnType, 42 | FromPool: pool, 43 | At: startAt + (i+1)*interval, 44 | } 45 | events = append(events, event) 46 | } 47 | return events 48 | } 49 | -------------------------------------------------------------------------------- /x/account/model/account.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/tendermint/tendermint/crypto" 6 | ttypes "github.com/tendermint/tendermint/types" 7 | 8 | "github.com/lino-network/lino/types" 9 | ) 10 | 11 | // AccountInfo - user information 12 | type AccountInfo struct { 13 | Username types.AccountKey `json:"username"` 14 | CreatedAt int64 `json:"created_at"` 15 | SigningKey crypto.PubKey `json:"signing_key"` 16 | TransactionKey crypto.PubKey `json:"transaction_key"` 17 | Address sdk.AccAddress `json:"address"` 18 | } 19 | 20 | // AccountBank - user balance 21 | type AccountBank struct { 22 | Saving types.Coin `json:"saving"` 23 | Pending types.Coin `json:"pending"` 24 | PubKey crypto.PubKey `json:"public_key"` 25 | Sequence uint64 `json:"sequence"` 26 | Username types.AccountKey `json:"username"` 27 | } 28 | 29 | // Pool - the pool for modules 30 | type Pool struct { 31 | Name types.PoolName `json:"name"` 32 | Balance types.Coin `json:"balance"` 33 | } 34 | 35 | // Supply - stats of lino supply. 36 | type Supply struct { 37 | LastYearTotal types.Coin `json:"last_year_total"` 38 | Total types.Coin `json:"total"` 39 | ChainStartTime int64 `json:"chain_start_time"` 40 | LastInflationTime int64 `json:"last_inflation_time"` 41 | } 42 | 43 | // AccountMeta - stores optional fields. 44 | type AccountMeta struct { 45 | JSONMeta string `json:"json_meta"` 46 | } 47 | 48 | type TxAndSequenceNumber struct { 49 | Username string `json:"username"` 50 | Sequence uint64 `json:"sequence"` 51 | Tx *Transaction `json:"tx"` 52 | } 53 | 54 | type Transaction struct { 55 | Hash string `json:"hash"` 56 | Height int64 `json:"height"` 57 | Tx ttypes.Tx `json:"tx"` 58 | Code uint32 `json:"code"` 59 | Log string `json:"log"` 60 | } 61 | -------------------------------------------------------------------------------- /x/developer/manager/input/common/AffiliatedBasic.input: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "testapp", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "testapp", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "", 14 | "description": "", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "1" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "testapp-max-affiliated", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "testapp-max-affliated", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "", 33 | "description": "", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "500" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "0", 42 | "key": "testuser-developer", 43 | "val": { 44 | "type": "lino/developer", 45 | "value": { 46 | "username": "testuser-developer", 47 | "deposit": { 48 | "amount": "0" 49 | }, 50 | "app_consumption": "0", 51 | "web_site": "", 52 | "description": "", 53 | "app_meta_data": "", 54 | "is_deleted": false, 55 | "n_affiliated": "0" 56 | } 57 | } 58 | }, 59 | { 60 | "prefix": "4", 61 | "key": "testapp/testuser-deactivate", 62 | "val": { 63 | "type": "str", 64 | "value": "t" 65 | } 66 | }, 67 | { 68 | "prefix": "5", 69 | "key": "testuser-affiliated", 70 | "val": { 71 | "type": "lino/role", 72 | "value": { 73 | "aa": "testapp-a" 74 | } 75 | } 76 | }, 77 | { 78 | "prefix": "5", 79 | "key": "testuser-deactivate", 80 | "val": { 81 | "type": "lino/role", 82 | "value": { 83 | "aa": "testapp" 84 | } 85 | } 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /x/vote/manager/mocks/StakingHooks.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v1.0.0. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | linotypes "github.com/lino-network/lino/types" 7 | 8 | mock "github.com/stretchr/testify/mock" 9 | 10 | types "github.com/cosmos/cosmos-sdk/types" 11 | ) 12 | 13 | // StakingHooks is an autogenerated mock type for the StakingHooks type 14 | type StakingHooks struct { 15 | mock.Mock 16 | } 17 | 18 | // AfterAddingStake provides a mock function with given fields: ctx, username 19 | func (_m *StakingHooks) AfterAddingStake(ctx types.Context, username linotypes.AccountKey) types.Error { 20 | ret := _m.Called(ctx, username) 21 | 22 | var r0 types.Error 23 | if rf, ok := ret.Get(0).(func(types.Context, linotypes.AccountKey) types.Error); ok { 24 | r0 = rf(ctx, username) 25 | } else { 26 | if ret.Get(0) != nil { 27 | r0 = ret.Get(0).(types.Error) 28 | } 29 | } 30 | 31 | return r0 32 | } 33 | 34 | // AfterSlashing provides a mock function with given fields: ctx, username 35 | func (_m *StakingHooks) AfterSlashing(ctx types.Context, username linotypes.AccountKey) types.Error { 36 | ret := _m.Called(ctx, username) 37 | 38 | var r0 types.Error 39 | if rf, ok := ret.Get(0).(func(types.Context, linotypes.AccountKey) types.Error); ok { 40 | r0 = rf(ctx, username) 41 | } else { 42 | if ret.Get(0) != nil { 43 | r0 = ret.Get(0).(types.Error) 44 | } 45 | } 46 | 47 | return r0 48 | } 49 | 50 | // AfterSubtractingStake provides a mock function with given fields: ctx, username 51 | func (_m *StakingHooks) AfterSubtractingStake(ctx types.Context, username linotypes.AccountKey) types.Error { 52 | ret := _m.Called(ctx, username) 53 | 54 | var r0 types.Error 55 | if rf, ok := ret.Get(0).(func(types.Context, linotypes.AccountKey) types.Error); ok { 56 | r0 = rf(ctx, username) 57 | } else { 58 | if ret.Get(0) != nil { 59 | r0 = ret.Get(0).(types.Error) 60 | } 61 | } 62 | 63 | return r0 64 | } 65 | -------------------------------------------------------------------------------- /x/price/model/golden/TestPriceStoreSuite/TestGetSetFeedHistory.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "4", 4 | "key": "", 5 | "val": { 6 | "type": "lino/price/feedhistory", 7 | "value": [ 8 | { 9 | "price": "1235", 10 | "feeded": [ 11 | { 12 | "validator": "val1", 13 | "price": "4567", 14 | "power": { 15 | "amount": "1000" 16 | }, 17 | "update_at": "1234" 18 | }, 19 | { 20 | "validator": "val2", 21 | "price": "7777", 22 | "power": { 23 | "amount": "1000" 24 | }, 25 | "update_at": "1255" 26 | }, 27 | { 28 | "validator": "val3", 29 | "price": "9999", 30 | "power": { 31 | "amount": "1000" 32 | }, 33 | "update_at": "1299" 34 | } 35 | ], 36 | "update_at": "12345" 37 | }, 38 | { 39 | "price": "7777", 40 | "feeded": [ 41 | { 42 | "validator": "val1", 43 | "price": "4567", 44 | "power": { 45 | "amount": "1000" 46 | }, 47 | "update_at": "1234" 48 | }, 49 | { 50 | "validator": "val2", 51 | "price": "7777", 52 | "power": { 53 | "amount": "1000" 54 | }, 55 | "update_at": "1255" 56 | }, 57 | { 58 | "validator": "val3", 59 | "price": "9999", 60 | "power": { 61 | "amount": "1000" 62 | }, 63 | "update_at": "1299" 64 | } 65 | ], 66 | "update_at": "567989" 67 | } 68 | ] 69 | } 70 | } 71 | ] 72 | -------------------------------------------------------------------------------- /types/error.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // NewError - create an error 10 | func NewError(code sdk.CodeType, msg string) sdk.Error { 11 | return sdk.NewError(LinoErrorCodeSpace, code, msg) 12 | } 13 | 14 | // ErrInvalidCoins - error if convert LNO to Coin failed 15 | func ErrInvalidCoins(msg string) sdk.Error { 16 | return NewError(CodeInvalidCoins, msg) 17 | } 18 | 19 | // ErrAmountOverflow - error if coin amount int64 overflow 20 | func ErrAmountOverflow() sdk.Error { 21 | return NewError(CodeInvalidInt64Number, "coin amount can't be represented as an int64") 22 | } 23 | 24 | // ErrInvalidQueryPath - error if query path length is incorrect or content is invalid 25 | func ErrInvalidQueryPath() sdk.Error { 26 | return NewError(CodeInvalidQueryPath, "query path is invalid") 27 | } 28 | 29 | // ErrQueryFailed - error if query path length is incorrect or content is invalid 30 | func ErrQueryFailed(reason string) sdk.Error { 31 | return NewError(CodeQueryFailed, "query failed: "+reason) 32 | } 33 | 34 | // ErrInvalidIDAAmount - error if the IDA amount is invalid. 35 | func ErrInvalidIDAAmount() sdk.Error { 36 | return NewError(CodeInvalidIDAAmount, "Invalid IDA amount") 37 | } 38 | 39 | // ErrUnimplemented - error if the feature is not implemented yet. 40 | func ErrUnimplemented(msg string) sdk.Error { 41 | return NewError(CodeUnimplementedError, msg) 42 | } 43 | 44 | // ErrInvalidUsername - error if the username is invalid. 45 | func ErrInvalidUsername(username AccountKey) sdk.Error { 46 | return NewError(CodeInvalidUsername, fmt.Sprintf("Invalid username: %s", username)) 47 | } 48 | 49 | // ErrUnknownEvent - unknown event. 50 | func ErrUnknownEvent() sdk.Error { 51 | return NewError(CodeUnknownEvent, "unknown event") 52 | } 53 | 54 | // ErrTestOnlyDummyError - 55 | func ErrTestDummyError() sdk.Error { 56 | return NewError(CodeTestDummyError, fmt.Sprintf("")) 57 | } 58 | -------------------------------------------------------------------------------- /x/global/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | // "fmt" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/codec" 8 | "github.com/spf13/cobra" 9 | 10 | linotypes "github.com/lino-network/lino/types" 11 | "github.com/lino-network/lino/utils" 12 | "github.com/lino-network/lino/x/global/model" 13 | types "github.com/lino-network/lino/x/global/types" 14 | ) 15 | 16 | func GetQueryCmd(cdc *codec.Codec) *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: types.ModuleName, 19 | Short: "Querying commands for the global module", 20 | DisableFlagParsing: true, 21 | SuggestionsMinimumDistance: 2, 22 | RunE: client.ValidateCmd, 23 | } 24 | cmd.AddCommand(client.GetCommands( 25 | // getCmdListEvents(cdc), 26 | utils.SimpleQueryCmd( 27 | "time", 28 | "time", 29 | types.QuerierRoute, types.QueryGlobalTime, 30 | 0, &model.GlobalTime{})(cdc), 31 | utils.SimpleQueryCmd( 32 | "event-errors", 33 | "event-errors", 34 | types.QuerierRoute, types.QueryGlobalEventErrors, 35 | 0, &([]model.EventError{}))(cdc), 36 | utils.SimpleQueryCmd( 37 | "bc-event-errors", 38 | "bc-event-errors", 39 | types.QuerierRoute, types.QueryGlobalBCEventErrors, 40 | 0, &([]linotypes.BCEventErr{}))(cdc), 41 | )...) 42 | return cmd 43 | } 44 | 45 | // // GetCmdListEvents - 46 | // func getCmdListEvents(cdc *codec.Codec) *cobra.Command { 47 | // return &cobra.Command{ 48 | // Use: "list-events", 49 | // Short: "list-events ", 50 | // Args: cobra.ExactArgs(1), 51 | // RunE: func(cmd *cobra.Command, args []string) error { 52 | // time := args[0] 53 | // uri := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, types.QueryTimeEventList, time) 54 | // rst := linotypes.TimeEventList{} 55 | // return utils.CLIQueryJSONPrint(cdc, uri, nil, 56 | // func() interface{} { return &rst }) 57 | // }, 58 | // } 59 | // } 60 | -------------------------------------------------------------------------------- /x/account/model/ir.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | crypto "github.com/tendermint/tendermint/crypto" 6 | 7 | "github.com/lino-network/lino/types" 8 | ) 9 | 10 | // AccountIR account related information when migrate, pk: Username 11 | type AccountIR struct { 12 | Username types.AccountKey `json:"username"` 13 | CreatedAt int64 `json:"created_at"` 14 | SigningKey crypto.PubKey `json:"signing_key"` 15 | TransactionKey crypto.PubKey `json:"transaction_key"` 16 | Address sdk.AccAddress `json:"address"` 17 | } 18 | 19 | // AccountBankIR - user balance 20 | type AccountBankIR struct { 21 | Address []byte `json:"address"` // pk 22 | Saving types.Coin `json:"saving"` 23 | Pending types.Coin `json:"pending"` 24 | PubKey crypto.PubKey `json:"public_key"` 25 | Sequence uint64 `json:"sequence"` 26 | Username types.AccountKey `json:"username"` 27 | } 28 | 29 | // AccountMetaIR - stores optional fields. 30 | type AccountMetaIR struct { 31 | Username types.AccountKey `json:"username"` 32 | JSONMeta string `json:"json_meta"` 33 | } 34 | 35 | // PoolIR - the module account. 36 | type PoolIR struct { 37 | Name types.PoolName `json:"name"` 38 | Balance types.Coin `json:"balance"` 39 | } 40 | 41 | // SupplyIR - stats of lino supply. 42 | type SupplyIR struct { 43 | LastYearTotal types.Coin `json:"last_year_total"` 44 | Total types.Coin `json:"total"` 45 | ChainStartTime int64 `json:"chain_start_time"` 46 | LastInflationTime int64 `json:"last_inflation_time"` 47 | } 48 | 49 | // AccountTablesIR - 50 | type AccountTablesIR struct { 51 | Version int `json:"version"` 52 | Accounts []AccountIR `json:"accounts"` 53 | Banks []AccountBankIR `json:"banks"` 54 | Metas []AccountMetaIR `json:"metas"` 55 | Pools []PoolIR `json:"pools"` 56 | Supply SupplyIR `json:"supply"` 57 | } 58 | -------------------------------------------------------------------------------- /x/validator/model/validator.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | abci "github.com/tendermint/tendermint/abci/types" 5 | "github.com/tendermint/tendermint/crypto" 6 | 7 | linotypes "github.com/lino-network/lino/types" 8 | ) 9 | 10 | // Validator is basic structure records all validator information 11 | type Validator struct { 12 | ABCIValidator abci.Validator `json:"abci_validator"` 13 | PubKey crypto.PubKey `json:"pubkey"` 14 | Username linotypes.AccountKey `json:"username"` 15 | ReceivedVotes linotypes.Coin `json:"received_votes"` 16 | HasRevoked bool `json:"has_revoked"` 17 | AbsentCommit int64 `json:"absent_commit"` 18 | ProducedBlocks int64 `json:"produced_blocks"` 19 | Link string `json:"link"` 20 | NumSlash int64 `json:"num_slash"` 21 | } 22 | 23 | type ElectionVote struct { 24 | ValidatorName linotypes.AccountKey `json:"validator_name"` 25 | Vote linotypes.Coin `json:"votes"` 26 | } 27 | 28 | type ReceivedVotesStatus struct { 29 | ValidatorName linotypes.AccountKey `json:"validator_name"` 30 | ReceivedVotes linotypes.Coin `json:"received_votes"` 31 | } 32 | 33 | type ElectionVoteList struct { 34 | ElectionVotes []ElectionVote `json:"election_votes"` 35 | } 36 | 37 | // ValidatorList 38 | type ValidatorList struct { 39 | Oncall []linotypes.AccountKey `json:"oncall"` 40 | Standby []linotypes.AccountKey `json:"standby"` 41 | Candidates []linotypes.AccountKey `json:"candidates"` 42 | Jail []linotypes.AccountKey `json:"jail"` 43 | PreBlockValidators []linotypes.AccountKey `json:"pre_block_validators"` 44 | LowestOncallVotes linotypes.Coin `json:"lowest_oncall_votes"` 45 | LowestOncall linotypes.AccountKey `json:"lowest_oncall"` 46 | LowestStandbyVotes linotypes.Coin `json:"lowest_standby_votes"` 47 | LowestStandby linotypes.AccountKey `json:"lowest_standby"` 48 | } 49 | -------------------------------------------------------------------------------- /x/validator/handler.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | 9 | "github.com/lino-network/lino/x/validator/types" 10 | ) 11 | 12 | // NewHandler - Handle all "validator" type messages. 13 | func NewHandler(vm ValidatorKeeper) sdk.Handler { 14 | return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { 15 | switch msg := msg.(type) { 16 | case types.ValidatorRegisterMsg: 17 | return handleValidatorRegisterMsg(ctx, vm, msg) 18 | case types.ValidatorRevokeMsg: 19 | return handleValidatorRevokeMsg(ctx, vm, msg) 20 | case types.VoteValidatorMsg: 21 | return handleVoteValidatorMsg(ctx, vm, msg) 22 | case types.ValidatorUpdateMsg: 23 | return handleValidatorUpdateMsg(ctx, vm, msg) 24 | default: 25 | errMsg := fmt.Sprintf("Unrecognized validator msg type: %v", reflect.TypeOf(msg).Name()) 26 | return sdk.ErrUnknownRequest(errMsg).Result() 27 | } 28 | } 29 | } 30 | 31 | func handleValidatorRegisterMsg(ctx sdk.Context, vm ValidatorKeeper, msg types.ValidatorRegisterMsg) sdk.Result { 32 | if err := vm.RegisterValidator(ctx, msg.Username, msg.ValPubKey, msg.Link); err != nil { 33 | return err.Result() 34 | } 35 | return sdk.Result{} 36 | } 37 | 38 | func handleValidatorRevokeMsg( 39 | ctx sdk.Context, vm ValidatorKeeper, msg types.ValidatorRevokeMsg) sdk.Result { 40 | if err := vm.RevokeValidator(ctx, msg.Username); err != nil { 41 | return err.Result() 42 | } 43 | return sdk.Result{} 44 | } 45 | 46 | func handleVoteValidatorMsg( 47 | ctx sdk.Context, vm ValidatorKeeper, msg types.VoteValidatorMsg) sdk.Result { 48 | if err := vm.VoteValidator(ctx, msg.Username, msg.VotedValidators); err != nil { 49 | return err.Result() 50 | } 51 | return sdk.Result{} 52 | } 53 | 54 | func handleValidatorUpdateMsg(ctx sdk.Context, vm ValidatorKeeper, msg types.ValidatorUpdateMsg) sdk.Result { 55 | if err := vm.UpdateValidator(ctx, msg.Username, msg.Link); err != nil { 56 | return err.Result() 57 | } 58 | return sdk.Result{} 59 | } 60 | -------------------------------------------------------------------------------- /x/vote/manager/golden/TestVoteManagerTestSuite/TestImportExport.golden: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "1", 4 | "key": "voter1", 5 | "val": { 6 | "type": "lino/voter", 7 | "value": { 8 | "username": "voter1", 9 | "lino_stake": { 10 | "amount": "1234" 11 | }, 12 | "last_power_change_at": "123", 13 | "interest": { 14 | "amount": "2345" 15 | }, 16 | "duty": "2", 17 | "frozen_amount": { 18 | "amount": "999" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "prefix": "1", 25 | "key": "voter2", 26 | "val": { 27 | "type": "lino/voter", 28 | "value": { 29 | "username": "voter2", 30 | "lino_stake": { 31 | "amount": "567" 32 | }, 33 | "last_power_change_at": "3", 34 | "interest": { 35 | "amount": "0" 36 | }, 37 | "duty": "0", 38 | "frozen_amount": { 39 | "amount": "0" 40 | } 41 | } 42 | } 43 | }, 44 | { 45 | "prefix": "2", 46 | "key": "0", 47 | "val": { 48 | "type": "lino/stakestats", 49 | "value": { 50 | "total_consumption_friction": { 51 | "amount": "123" 52 | }, 53 | "unclaimed_friction": { 54 | "amount": "456" 55 | }, 56 | "total_lino_power": { 57 | "amount": "789" 58 | }, 59 | "unclaimed_lino_power": { 60 | "amount": "1230" 61 | } 62 | } 63 | } 64 | }, 65 | { 66 | "prefix": "2", 67 | "key": "1", 68 | "val": { 69 | "type": "lino/stakestats", 70 | "value": { 71 | "total_consumption_friction": { 72 | "amount": "1123" 73 | }, 74 | "unclaimed_friction": { 75 | "amount": "1456" 76 | }, 77 | "total_lino_power": { 78 | "amount": "1789" 79 | }, 80 | "unclaimed_lino_power": { 81 | "amount": "11230" 82 | } 83 | } 84 | } 85 | } 86 | ] 87 | -------------------------------------------------------------------------------- /x/developer/model/load.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "prefix": "0", 4 | "key": "test", 5 | "val": { 6 | "type": "lino/developer", 7 | "value": { 8 | "username": "test", 9 | "deposit": { 10 | "amount": "0" 11 | }, 12 | "app_consumption": "0", 13 | "web_site": "web1", 14 | "description": "desc1", 15 | "app_meta_data": "", 16 | "is_deleted": false, 17 | "n_affiliated": "0" 18 | } 19 | } 20 | }, 21 | { 22 | "prefix": "0", 23 | "key": "test2", 24 | "val": { 25 | "type": "lino/developer", 26 | "value": { 27 | "username": "test2", 28 | "deposit": { 29 | "amount": "0" 30 | }, 31 | "app_consumption": "0", 32 | "web_site": "web2", 33 | "description": "desc2", 34 | "app_meta_data": "", 35 | "is_deleted": false, 36 | "n_affiliated": "0" 37 | } 38 | } 39 | }, 40 | { 41 | "prefix": "1", 42 | "key": "app1", 43 | "val": { 44 | "type": "lino/appida", 45 | "value": { 46 | "app": "app1", 47 | "name": "appname1", 48 | "price": "0", 49 | "is_revoked": true, 50 | "revoke_coin_price": "333" 51 | } 52 | } 53 | }, 54 | { 55 | "prefix": "2", 56 | "key": "app1/user1", 57 | "val": { 58 | "type": "lino/bank", 59 | "value": { 60 | "b": "33" 61 | } 62 | } 63 | }, 64 | { 65 | "prefix": "3", 66 | "key": "", 67 | "val": { 68 | "type": "lino/reservepool", 69 | "value": { 70 | "total": { 71 | "amount": "444" 72 | }, 73 | "total_minidollar": "333" 74 | } 75 | } 76 | }, 77 | { 78 | "prefix": "4", 79 | "key": "app1/user1", 80 | "val": { 81 | "type": "str", 82 | "value": "t" 83 | } 84 | }, 85 | { 86 | "prefix": "5", 87 | "key": "user2", 88 | "val": { 89 | "type": "lino/role", 90 | "value": { 91 | "aa": "app3" 92 | } 93 | } 94 | } 95 | ] --------------------------------------------------------------------------------