Merge basecoin with tendermint_classic

This commit is contained in:
Jae Kwon
2016-03-21 15:31:25 -07:00
parent 3d8cb897b8
commit 5049c35efc
14 changed files with 789 additions and 398 deletions
+44
View File
@@ -0,0 +1,44 @@
package types
import (
"fmt"
"github.com/tendermint/go-crypto"
)
type Account struct {
PubKey crypto.PubKey // May be nil, if not known.
Sequence int
Balance int64
}
func (acc *Account) Copy() *Account {
accCopy := *acc
return &accCopy
}
func (acc *Account) String() string {
if acc == nil {
return "nil-Account"
}
return fmt.Sprintf("Account{%v %v %v}",
acc.PubKey, acc.Sequence, acc.Balance)
}
//----------------------------------------
type PrivAccount struct {
crypto.PrivKey
Account
}
//----------------------------------------
type AccountGetter interface {
GetAccount(addr []byte) *Account
}
type AccountGetterSetter interface {
GetAccount(addr []byte) *Account
SetAccount(acc *Account)
}
+21
View File
@@ -0,0 +1,21 @@
package types
import (
tmsp "github.com/tendermint/tmsp/types"
)
var (
ErrDuplicateAddress = tmsp.NewError(tmsp.CodeType_BaseDuplicateAddress, "Error duplicate address")
ErrEncodingError = tmsp.NewError(tmsp.CodeType_BaseEncodingError, "Error encoding error")
ErrInsufficientFees = tmsp.NewError(tmsp.CodeType_BaseInsufficientFees, "Error insufficient fees")
ErrInsufficientFunds = tmsp.NewError(tmsp.CodeType_BaseInsufficientFunds, "Error insufficient funds")
ErrInsufficientGasPrice = tmsp.NewError(tmsp.CodeType_BaseInsufficientGasPrice, "Error insufficient gas price")
ErrInvalidAddress = tmsp.NewError(tmsp.CodeType_BaseInvalidAddress, "Error invalid address")
ErrInvalidAmount = tmsp.NewError(tmsp.CodeType_BaseInvalidAmount, "Error invalid amount")
ErrInvalidPubKey = tmsp.NewError(tmsp.CodeType_BaseInvalidPubKey, "Error invalid pubkey")
ErrInvalidSequence = tmsp.NewError(tmsp.CodeType_BaseInvalidSequence, "Error invalid sequence")
ErrInvalidSignature = tmsp.NewError(tmsp.CodeType_BaseInvalidSignature, "Error invalid signature")
ErrUnknownPubKey = tmsp.NewError(tmsp.CodeType_BaseUnknownPubKey, "Error unknown pubkey")
ResultOK = tmsp.NewResultOK(nil, "")
)
+6
View File
@@ -0,0 +1,6 @@
package types
type Plugin func(ags AccountGetterSetter,
caller *Account,
input []byte,
gas *int64) (result []byte, err error)
+174
View File
@@ -0,0 +1,174 @@
package types
import (
"bytes"
"encoding/json"
. "github.com/tendermint/go-common"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
"golang.org/x/crypto/ripemd160"
)
/*
Tx (Transaction) is an atomic operation on the ledger state.
Account Types:
- SendTx Send coins to address
- CallTx Send a msg to a contract that runs in the vm
*/
type Tx interface {
SignBytes(chainID string) []byte
}
// Types of Tx implementations
const (
// Account transactions
TxTypeSend = byte(0x01)
TxTypeCall = byte(0x02)
)
var _ = wire.RegisterInterface(
struct{ Tx }{},
wire.ConcreteType{&SendTx{}, TxTypeSend},
wire.ConcreteType{&CallTx{}, TxTypeCall},
)
//-----------------------------------------------------------------------------
type TxInput struct {
Address []byte `json:"address"` // Hash of the PubKey
Amount int64 `json:"amount"` // Must not exceed account balance
Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput
Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx
PubKey crypto.PubKey `json:"pub_key"` // May be nil
}
func (txIn TxInput) ValidateBasic() error {
if len(txIn.Address) != 20 {
return ErrInvalidAddress
}
if txIn.Amount == 0 {
return ErrInvalidAmount
}
return nil
}
func (txIn TxInput) SignBytes() []byte {
return []byte(Fmt(`{"address":"%X","amount":%v,"sequence":%v}`,
txIn.Address, txIn.Amount, txIn.Sequence))
}
func (txIn TxInput) String() string {
return Fmt("TxInput{%X,%v,%v,%v,%v}", txIn.Address, txIn.Amount, txIn.Sequence, txIn.Signature, txIn.PubKey)
}
//-----------------------------------------------------------------------------
type TxOutput struct {
Address []byte `json:"address"` // Hash of the PubKey
Amount int64 `json:"amount"` // The sum of all outputs must not exceed the inputs.
}
func (txOut TxOutput) ValidateBasic() error {
if len(txOut.Address) != 20 {
return ErrInvalidAddress
}
if txOut.Amount == 0 {
return ErrInvalidAmount
}
return nil
}
func (txOut TxOutput) SignBytes() []byte {
return []byte(Fmt(`{"address":"%X","amount":%v}`,
txOut.Address, txOut.Amount))
}
func (txOut TxOutput) String() string {
return Fmt("TxOutput{%X,%v}", txOut.Address, txOut.Amount)
}
//-----------------------------------------------------------------------------
type SendTx struct {
Inputs []TxInput `json:"inputs"`
Outputs []TxOutput `json:"outputs"`
}
func (tx *SendTx) SignBytes(chainID string) []byte {
var buf = new(bytes.Buffer)
buf.Write([]byte(Fmt(`{"chain_id":%s`, jsonEscape(chainID))))
buf.Write([]byte(Fmt(`,"tx":[%v,{"inputs":[`, TxTypeSend)))
for i, in := range tx.Inputs {
buf.Write(in.SignBytes())
if i != len(tx.Inputs)-1 {
buf.Write([]byte(","))
}
}
buf.Write([]byte(`],"outputs":[`))
for i, out := range tx.Outputs {
buf.Write(out.SignBytes())
if i != len(tx.Outputs)-1 {
buf.Write([]byte(","))
}
}
buf.Write([]byte(`]}]}`))
return buf.Bytes()
}
func (tx *SendTx) String() string {
return Fmt("SendTx{%v -> %v}", tx.Inputs, tx.Outputs)
}
//-----------------------------------------------------------------------------
type CallTx struct {
Input TxInput `json:"input"`
Address []byte `json:"address"`
GasLimit int64 `json:"gas_limit"`
Fee int64 `json:"fee"`
Data []byte `json:"data"`
}
func (tx *CallTx) SignBytes(chainID string) []byte {
var buf = new(bytes.Buffer)
buf.Write([]byte(Fmt(`{"chain_id":%s`, jsonEscape(chainID))))
buf.Write([]byte(Fmt(`,"tx":[%v,{"address":"%X","data":"%X"`, TxTypeCall, tx.Address, tx.Data)))
buf.Write([]byte(Fmt(`,"fee":%v,"gas_limit":%v,"input":`, tx.Fee, tx.GasLimit)))
buf.Write(tx.Input.SignBytes())
buf.Write([]byte(`}]}`))
return buf.Bytes()
}
func (tx *CallTx) String() string {
return Fmt("CallTx{%v -> %x: %x}", tx.Input, tx.Address, tx.Data)
}
func NewContractAddress(caller []byte, nonce int) []byte {
temp := make([]byte, 32+8)
copy(temp, caller)
PutInt64BE(temp[32:], int64(nonce))
hasher := ripemd160.New()
hasher.Write(temp) // does not error
return hasher.Sum(nil)
}
//-----------------------------------------------------------------------------
func TxID(chainID string, tx Tx) []byte {
signBytes := tx.SignBytes(chainID)
return wire.BinaryRipemd160(signBytes)
}
//--------------------------------------------------------------------------------
// Contract: This function is deterministic and completely reversible.
func jsonEscape(str string) string {
escapedBytes, err := json.Marshal(str)
if err != nil {
PanicSanity(Fmt("Error json-escaping a string", str))
}
return string(escapedBytes)
}
+64
View File
@@ -0,0 +1,64 @@
package types
import (
"testing"
. "github.com/tendermint/go-common"
)
var chainID string = "test_chain"
func TestSendTxSignable(t *testing.T) {
sendTx := &SendTx{
Inputs: []TxInput{
TxInput{
Address: []byte("input1"),
Amount: 12345,
Sequence: 67890,
},
TxInput{
Address: []byte("input2"),
Amount: 111,
Sequence: 222,
},
},
Outputs: []TxOutput{
TxOutput{
Address: []byte("output1"),
Amount: 333,
},
TxOutput{
Address: []byte("output2"),
Amount: 444,
},
},
}
signBytes := sendTx.SignBytes(chainID)
signStr := string(signBytes)
expected := Fmt(`{"chain_id":"%s","tx":[1,{"inputs":[{"address":"696E70757431","amount":12345,"sequence":67890},{"address":"696E70757432","amount":111,"sequence":222}],"outputs":[{"address":"6F757470757431","amount":333},{"address":"6F757470757432","amount":444}]}]}`,
chainID)
if signStr != expected {
t.Errorf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signStr)
}
}
func TestCallTxSignable(t *testing.T) {
callTx := &CallTx{
Input: TxInput{
Address: []byte("input1"),
Amount: 12345,
Sequence: 67890,
},
Address: []byte("contract1"),
GasLimit: 111,
Fee: 222,
Data: []byte("data1"),
}
signBytes := callTx.SignBytes(chainID)
signStr := string(signBytes)
expected := Fmt(`{"chain_id":"%s","tx":[2,{"address":"636F6E747261637431","data":"6461746131","fee":222,"gas_limit":111,"input":{"address":"696E70757431","amount":12345,"sequence":67890}}]}`,
chainID)
if signStr != expected {
t.Errorf("Got unexpected sign string for CallTx. Expected:\n%v\nGot:\n%v", expected, signStr)
}
}
-100
View File
@@ -1,100 +0,0 @@
package types
import (
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
gov "github.com/tendermint/governmint/types"
)
type Input struct {
PubKey crypto.PubKey
Amount uint64
Sequence uint
Signature crypto.Signature
}
type Output struct {
PubKey crypto.PubKey
Amount uint64
}
type SendTx struct {
Inputs []Input
Outputs []Output
}
func (tx *SendTx) SignBytes() []byte {
sigs := make([]crypto.Signature, len(tx.Inputs))
for i, input := range tx.Inputs {
sigs[i] = input.Signature
input.Signature = nil
tx.Inputs[i] = input
}
signBytes := wire.BinaryBytes(tx)
for i := range tx.Inputs {
tx.Inputs[i].Signature = sigs[i]
}
return signBytes
}
func (tx *SendTx) GetInputs() []Input { return tx.Inputs }
func (tx *SendTx) GetOutputs() []Output { return tx.Outputs }
type GovTx struct {
Input Input
Tx gov.Tx
}
func (tx *GovTx) SignBytes() []byte {
sig := tx.Input.Signature
tx.Input.Signature = nil
signBytes := wire.BinaryBytes(tx)
tx.Input.Signature = sig
return signBytes
}
func (tx *GovTx) GetInputs() []Input { return []Input{tx.Input} }
func (tx *GovTx) GetOutputs() []Output { return nil }
type Tx interface {
AssertIsTx()
SignBytes() []byte
GetInputs() []Input
GetOutputs() []Output
}
func (_ *SendTx) AssertIsTx() {}
func (_ *GovTx) AssertIsTx() {}
const (
TxTypeSend = byte(0x01)
TxTypeGov = byte(0x02)
)
var _ = wire.RegisterInterface(
struct{ Tx }{},
wire.ConcreteType{&SendTx{}, TxTypeSend},
wire.ConcreteType{&GovTx{}, TxTypeGov},
)
//----------------------------------------
type Account struct {
Sequence uint
Balance uint64
}
type PubAccount struct {
crypto.PubKey
Account
}
type PrivAccount struct {
crypto.PubKey
crypto.PrivKey
Account
}
type GenesisState struct {
Accounts []PubAccount
}