mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-26 19:21:44 +00:00
update namereg with longer names, more allowed chars
This commit is contained in:
@ -198,7 +198,7 @@ func testNameReg(t *testing.T, typ string) {
|
|||||||
data := "if not now, when"
|
data := "if not now, when"
|
||||||
fee := int64(1000)
|
fee := int64(1000)
|
||||||
numDesiredBlocks := int64(2)
|
numDesiredBlocks := int64(2)
|
||||||
amt := fee + numDesiredBlocks*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt := fee + numDesiredBlocks*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
|
|
||||||
eid := types.EventStringNameReg(name)
|
eid := types.EventStringNameReg(name)
|
||||||
subscribe(t, con, eid)
|
subscribe(t, con, eid)
|
||||||
@ -243,7 +243,7 @@ func testNameReg(t *testing.T, typ string) {
|
|||||||
// update the data as the owner, make sure still there
|
// update the data as the owner, make sure still there
|
||||||
numDesiredBlocks = int64(2)
|
numDesiredBlocks = int64(2)
|
||||||
data = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need"
|
data = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need"
|
||||||
amt = fee + numDesiredBlocks*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt = fee + numDesiredBlocks*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
tx = makeDefaultNameTx(t, typ, name, data, amt, fee)
|
tx = makeDefaultNameTx(t, typ, name, data, amt, fee)
|
||||||
broadcastTx(t, typ, tx)
|
broadcastTx(t, typ, tx)
|
||||||
// commit block
|
// commit block
|
||||||
|
@ -543,14 +543,13 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
|
|
||||||
// validate the input strings
|
// validate the input strings
|
||||||
if err := tx.ValidateStrings(); err != nil {
|
if err := tx.ValidateStrings(); err != nil {
|
||||||
log.Info(err.Error())
|
return err
|
||||||
return types.ErrTxInvalidString
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value := tx.Input.Amount - tx.Fee
|
value := tx.Input.Amount - tx.Fee
|
||||||
|
|
||||||
// let's say cost of a name for one block is len(data) + 32
|
// let's say cost of a name for one block is len(data) + 32
|
||||||
costPerBlock := types.NameCostPerBlock * types.NameCostPerByte * tx.BaseEntryCost()
|
costPerBlock := types.NameCostPerBlock(types.NameBaseCost(tx.Name, tx.Data))
|
||||||
expiresIn := int(value / costPerBlock)
|
expiresIn := int(value / costPerBlock)
|
||||||
lastBlockHeight := _s.LastBlockHeight
|
lastBlockHeight := _s.LastBlockHeight
|
||||||
|
|
||||||
@ -591,7 +590,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
} else {
|
} else {
|
||||||
// since the size of the data may have changed
|
// since the size of the data may have changed
|
||||||
// we use the total amount of "credit"
|
// we use the total amount of "credit"
|
||||||
oldCredit := int64(entry.Expires-lastBlockHeight) * types.BaseEntryCost(entry.Name, entry.Data)
|
oldCredit := int64(entry.Expires-lastBlockHeight) * types.NameBaseCost(entry.Name, entry.Data)
|
||||||
credit := oldCredit + value
|
credit := oldCredit + value
|
||||||
expiresIn = int(credit / costPerBlock)
|
expiresIn = int(credit / costPerBlock)
|
||||||
if expiresIn < types.MinNameRegistrationPeriod {
|
if expiresIn < types.MinNameRegistrationPeriod {
|
||||||
|
@ -219,12 +219,12 @@ func TestNameTxs(t *testing.T) {
|
|||||||
startingBlock := state.LastBlockHeight
|
startingBlock := state.LastBlockHeight
|
||||||
|
|
||||||
// try some bad names. these should all fail
|
// try some bad names. these should all fail
|
||||||
names := []string{"", "\n", "123#$%", "\x00", string([]byte{20, 40, 60, 80}), "baffledbythespectacleinallofthisyouseeehesaidwithouteyes", "no spaces please"}
|
names := []string{"", "\n", "123#$%", "\x00", string([]byte{20, 40, 60, 80}), "baffledbythespectacleinallofthisyouseeehesaidwithouteyessurprised", "no spaces please"}
|
||||||
data := "something about all this just doesn't feel right."
|
data := "something about all this just doesn't feel right."
|
||||||
fee := int64(1000)
|
fee := int64(1000)
|
||||||
numDesiredBlocks := 5
|
numDesiredBlocks := 5
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
amt := fee + int64(numDesiredBlocks)*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt := fee + int64(numDesiredBlocks)*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
||||||
tx.Sign(state.ChainID, privAccounts[0])
|
tx.Sign(state.ChainID, privAccounts[0])
|
||||||
|
|
||||||
@ -237,7 +237,7 @@ func TestNameTxs(t *testing.T) {
|
|||||||
name := "hold_it_chum"
|
name := "hold_it_chum"
|
||||||
datas := []string{"cold&warm", "!@#$%^&*()", "<<<>>>>", "because why would you ever need a ~ or a & or even a % in a json file? make your case and we'll talk"}
|
datas := []string{"cold&warm", "!@#$%^&*()", "<<<>>>>", "because why would you ever need a ~ or a & or even a % in a json file? make your case and we'll talk"}
|
||||||
for _, data := range datas {
|
for _, data := range datas {
|
||||||
amt := fee + int64(numDesiredBlocks)*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt := fee + int64(numDesiredBlocks)*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
||||||
tx.Sign(state.ChainID, privAccounts[0])
|
tx.Sign(state.ChainID, privAccounts[0])
|
||||||
|
|
||||||
@ -266,9 +266,9 @@ func TestNameTxs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try a good one, check data, owner, expiry
|
// try a good one, check data, owner, expiry
|
||||||
name = "looking_good/karaoke_bar"
|
name = "@looking_good/karaoke_bar.broadband"
|
||||||
data = "on this side of neptune there are 1234567890 people: first is OMNIVORE. Or is it. Ok this is pretty restrictive. No exclamations :(. Faces tho :')"
|
data = "on this side of neptune there are 1234567890 people: first is OMNIVORE+-3. Or is it. Ok this is pretty restrictive. No exclamations :(. Faces tho :')"
|
||||||
amt := fee + int64(numDesiredBlocks)*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt := fee + int64(numDesiredBlocks)*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
tx, _ := types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
||||||
tx.Sign(state.ChainID, privAccounts[0])
|
tx.Sign(state.ChainID, privAccounts[0])
|
||||||
if err := execTxWithState(state, tx, true); err != nil {
|
if err := execTxWithState(state, tx, true); err != nil {
|
||||||
@ -325,7 +325,7 @@ func TestNameTxs(t *testing.T) {
|
|||||||
data = "In the beginning there was no thing, not even the beginning. It hadn't been here, no there, nor for that matter anywhere, not especially because it had not to even exist, let alone to not. Nothing especially odd about that."
|
data = "In the beginning there was no thing, not even the beginning. It hadn't been here, no there, nor for that matter anywhere, not especially because it had not to even exist, let alone to not. Nothing especially odd about that."
|
||||||
oldCredit := amt - fee
|
oldCredit := amt - fee
|
||||||
numDesiredBlocks = 10
|
numDesiredBlocks = 10
|
||||||
amt = fee + (int64(numDesiredBlocks)*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data) - oldCredit)
|
amt = fee + (int64(numDesiredBlocks)*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data) - oldCredit)
|
||||||
tx, _ = types.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
|
tx, _ = types.NewNameTx(state, privAccounts[1].PubKey, name, data, amt, fee)
|
||||||
tx.Sign(state.ChainID, privAccounts[1])
|
tx.Sign(state.ChainID, privAccounts[1])
|
||||||
if err := execTxWithState(state, tx, true); err != nil {
|
if err := execTxWithState(state, tx, true); err != nil {
|
||||||
@ -351,7 +351,7 @@ func TestNameTxs(t *testing.T) {
|
|||||||
// test removal by key1 after expiry
|
// test removal by key1 after expiry
|
||||||
name = "looking_good/karaoke_bar"
|
name = "looking_good/karaoke_bar"
|
||||||
data = "some data"
|
data = "some data"
|
||||||
amt = fee + int64(numDesiredBlocks)*types.NameCostPerByte*types.NameCostPerBlock*types.BaseEntryCost(name, data)
|
amt = fee + int64(numDesiredBlocks)*types.NameByteCostMultiplier*types.NameBlockCostMultiplier*types.NameBaseCost(name, data)
|
||||||
tx, _ = types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
tx, _ = types.NewNameTx(state, privAccounts[0].PubKey, name, data, amt, fee)
|
||||||
tx.Sign(state.ChainID, privAccounts[0])
|
tx.Sign(state.ChainID, privAccounts[0])
|
||||||
if err := execTxWithState(state, tx, true); err != nil {
|
if err := execTxWithState(state, tx, true); err != nil {
|
||||||
@ -511,7 +511,7 @@ proof-of-work chain as proof of what happened while they were gone `
|
|||||||
tx.Input.Sequence += 1
|
tx.Input.Sequence += 1
|
||||||
tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
|
tx.Input.Signature = privAccounts[0].Sign(state.ChainID, tx)
|
||||||
err = execTxWithState(state, tx, true)
|
err = execTxWithState(state, tx, true)
|
||||||
if err != types.ErrTxInvalidString {
|
if _, ok := err.(types.ErrTxInvalidString); !ok {
|
||||||
t.Errorf("Expected invalid string error. Got: %s", err.Error())
|
t.Errorf("Expected invalid string error. Got: %s", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,16 +12,16 @@ var (
|
|||||||
|
|
||||||
// cost for storing a name for a block is
|
// cost for storing a name for a block is
|
||||||
// CostPerBlock*CostPerByte*(len(data) + 32)
|
// CostPerBlock*CostPerByte*(len(data) + 32)
|
||||||
NameCostPerByte int64 = 1
|
NameByteCostMultiplier int64 = 1
|
||||||
NameCostPerBlock int64 = 1
|
NameBlockCostMultiplier int64 = 1
|
||||||
|
|
||||||
MaxNameLength = 32
|
MaxNameLength = 64
|
||||||
MaxDataLength = 1 << 16
|
MaxDataLength = 1 << 16
|
||||||
|
|
||||||
// Name should be alphanum, underscore, slash
|
// Name should be file system lik
|
||||||
// Data should be anything permitted in JSON
|
// Data should be anything permitted in JSON
|
||||||
regexpAlphaNum = regexp.MustCompile("^[a-zA-Z0-9._/]*$")
|
regexpAlphaNum = regexp.MustCompile("^[a-zA-Z0-9._/-@]*$")
|
||||||
regexpJSON = regexp.MustCompile(`^[a-zA-Z0-9_/ \-"':,\n\t.{}()\[\]]*$`)
|
regexpJSON = regexp.MustCompile(`^[a-zA-Z0-9_/ \-+"':,\n\t.{}()\[\]]*$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// filter strings
|
// filter strings
|
||||||
@ -34,10 +34,14 @@ func validateNameRegEntryData(data string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// base cost is "effective" number of bytes
|
// base cost is "effective" number of bytes
|
||||||
func BaseEntryCost(name, data string) int64 {
|
func NameBaseCost(name, data string) int64 {
|
||||||
return int64(len(data) + 32)
|
return int64(len(data) + 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NameCostPerBlock(baseCost int64) int64 {
|
||||||
|
return NameBlockCostMultiplier * NameByteCostMultiplier * baseCost
|
||||||
|
}
|
||||||
|
|
||||||
type NameRegEntry struct {
|
type NameRegEntry struct {
|
||||||
Name string `json:"name"` // registered name for the entry
|
Name string `json:"name"` // registered name for the entry
|
||||||
Owner []byte `json:"owner"` // address that created the entry
|
Owner []byte `json:"owner"` // address that created the entry
|
||||||
|
23
types/tx.go
23
types/tx.go
@ -22,10 +22,17 @@ var (
|
|||||||
ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
|
ErrTxUnknownPubKey = errors.New("Error unknown pubkey")
|
||||||
ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
|
ErrTxInvalidPubKey = errors.New("Error invalid pubkey")
|
||||||
ErrTxInvalidSignature = errors.New("Error invalid signature")
|
ErrTxInvalidSignature = errors.New("Error invalid signature")
|
||||||
ErrTxInvalidString = errors.New("Error invalid string")
|
|
||||||
ErrTxPermissionDenied = errors.New("Error permission denied")
|
ErrTxPermissionDenied = errors.New("Error permission denied")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ErrTxInvalidString struct {
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrTxInvalidString) Error() string {
|
||||||
|
return e.Msg
|
||||||
|
}
|
||||||
|
|
||||||
type ErrTxInvalidSequence struct {
|
type ErrTxInvalidSequence struct {
|
||||||
Got int
|
Got int
|
||||||
Expected int
|
Expected int
|
||||||
@ -220,30 +227,26 @@ func (tx *NameTx) WriteSignBytes(chainID string, w io.Writer, n *int64, err *err
|
|||||||
|
|
||||||
func (tx *NameTx) ValidateStrings() error {
|
func (tx *NameTx) ValidateStrings() error {
|
||||||
if len(tx.Name) == 0 {
|
if len(tx.Name) == 0 {
|
||||||
return errors.New("Name must not be empty")
|
return ErrTxInvalidString{"Name must not be empty"}
|
||||||
}
|
}
|
||||||
if len(tx.Name) > MaxNameLength {
|
if len(tx.Name) > MaxNameLength {
|
||||||
return errors.New(Fmt("Name is too long. Max %d bytes", MaxNameLength))
|
return ErrTxInvalidString{Fmt("Name is too long. Max %d bytes", MaxNameLength)}
|
||||||
}
|
}
|
||||||
if len(tx.Data) > MaxDataLength {
|
if len(tx.Data) > MaxDataLength {
|
||||||
return errors.New(Fmt("Data is too long. Max %d bytes", MaxDataLength))
|
return ErrTxInvalidString{Fmt("Data is too long. Max %d bytes", MaxDataLength)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !validateNameRegEntryName(tx.Name) {
|
if !validateNameRegEntryName(tx.Name) {
|
||||||
return errors.New(Fmt("Invalid characters found in NameTx.Name (%s). Only alphanumeric, underscores, and forward slashes allowed", tx.Name))
|
return ErrTxInvalidString{Fmt("Invalid characters found in NameTx.Name (%s). Only alphanumeric, underscores, dashes, forward slashes, and @ are allowed", tx.Name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !validateNameRegEntryData(tx.Data) {
|
if !validateNameRegEntryData(tx.Data) {
|
||||||
return errors.New(Fmt("Invalid characters found in NameTx.Data (%s). Only the kind of things found in a JSON file are allowed", tx.Data))
|
return ErrTxInvalidString{Fmt("Invalid characters found in NameTx.Data (%s). Only the kind of things found in a JSON file are allowed", tx.Data)}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *NameTx) BaseEntryCost() int64 {
|
|
||||||
return BaseEntryCost(tx.Name, tx.Data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tx *NameTx) String() string {
|
func (tx *NameTx) String() string {
|
||||||
return Fmt("NameTx{%v -> %s: %s}", tx.Input, tx.Name, tx.Data)
|
return Fmt("NameTx{%v -> %s: %s}", tx.Input, tx.Name, tx.Data)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user