update namereg with longer names, more allowed chars

This commit is contained in:
Ethan Buchman
2015-09-15 18:39:01 -04:00
parent 78768082a1
commit e4f0e2b399
5 changed files with 38 additions and 32 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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())
} }
} }

View File

@ -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

View File

@ -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)
} }