This commit is contained in:
Ethan Buchman
2015-05-22 16:53:10 -04:00
parent 1f6d64b91c
commit 8631d5085e
7 changed files with 348 additions and 1 deletions

View File

@ -296,7 +296,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
// TODO: do something with fees
fees := uint64(0)
_s := blockCache.State() // hack to access validators and event switch.
_s := blockCache.State() // hack to access validators and block height
// Exec tx
switch tx := tx_.(type) {
@ -478,6 +478,102 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
return nil
case *types.NameTx:
var inAcc *account.Account
// Validate input
inAcc = blockCache.GetAccount(tx.Input.Address)
if inAcc == nil {
log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
return types.ErrTxInvalidAddress
}
// pubKey should be present in either "inAcc" or "tx.Input"
if err := checkInputPubKey(inAcc, tx.Input); err != nil {
log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
return err
}
signBytes := account.SignBytes(tx)
err := validateInput(inAcc, signBytes, tx.Input)
if err != nil {
log.Debug(Fmt("validateInput failed on %X:", tx.Input.Address))
return err
}
// fee is in addition to the amount which is used to determine the TTL
if tx.Input.Amount < tx.Fee {
log.Debug(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
return types.ErrTxInsufficientFunds
}
value := tx.Input.Amount - tx.Fee
// let's say cost of a name for one block is len(data) + 32
// TODO: the casting is dangerous and things can overflow (below)!
// we should make LastBlockHeight a uint64
costPerBlock := uint(len(tx.Data) + 32)
expiresIn := uint(value / uint64(costPerBlock))
// check if the name exists
entry := blockCache.GetNameRegEntry(tx.Name)
if entry != nil {
var expired bool
// if the entry already exists, and hasn't expired, we must be owner
if entry.Expires > _s.LastBlockHeight {
// ensure we are owner
if bytes.Compare(entry.Owner, tx.Input.Address) != 0 {
log.Debug(Fmt("Sender %X is trying to update a name (%s) for which he is not owner", tx.Input.Address, tx.Name))
return types.ErrTxInvalidAddress // (?)
}
} else {
expired = true
}
// no value and empty data means delete the entry
if value == 0 && len(tx.Data) == 0 {
// maybe we reward you for telling us we can delete this crap
// (owners if not expired, anyone if expired)
blockCache.RemoveNameRegEntry(entry.Name)
} else {
// update the entry by bumping the expiry
// and changing the data
if expired {
entry.Expires = _s.LastBlockHeight + expiresIn
} else {
// since the size of the data may have changed
// we use the total amount of "credit"
credit := uint64((entry.Expires - _s.LastBlockHeight) * uint(len(entry.Data)))
credit += value
expiresIn = uint(credit) / costPerBlock
entry.Expires = _s.LastBlockHeight + expiresIn
}
entry.Data = tx.Data
blockCache.UpdateNameRegEntry(entry)
}
} else {
if expiresIn < 5 {
return fmt.Errorf("Names must be registered for at least 5 blocks")
}
// entry does not exist, so create it
entry = &types.NameRegEntry{
Name: tx.Name,
Owner: tx.Input.Address,
Data: tx.Data,
Expires: _s.LastBlockHeight + expiresIn,
}
blockCache.UpdateNameRegEntry(entry)
}
// TODO: something with the value sent?
// Good!
inAcc.Sequence += 1
inAcc.Balance -= value
blockCache.UpdateAccount(inAcc)
// TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
return nil
case *types.BondTx:
valInfo := blockCache.State().GetValidatorInfo(tx.PubKey.Address())
if valInfo != nil {