コード例 #1
0
ファイル: api.go プロジェクト: efaysal/etherapis
// Call forms a transaction from the given arguments and tries to execute it on
// a private VM with a copy of the state. Any changes are therefore only temporary
// and not part of the actual state. This allows for local execution/queries.
func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) {
	block := be.bc.CurrentBlock()
	statedb, err := state.New(block.Root(), be.chainDb)
	if err != nil {
		return "", "", err
	}

	var from *state.StateObject
	if len(fromStr) == 0 {
		accounts, err := be.am.Accounts()
		if err != nil || len(accounts) == 0 {
			from = statedb.GetOrNewStateObject(common.Address{})
		} else {
			from = statedb.GetOrNewStateObject(accounts[0].Address)
		}
	} else {
		from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr))
	}

	from.SetBalance(common.MaxBig)

	msg := callmsg{
		from:     from,
		gas:      common.Big(gasStr),
		gasPrice: common.Big(gasPriceStr),
		value:    common.Big(valueStr),
		data:     common.FromHex(dataStr),
	}
	if len(toStr) > 0 {
		addr := common.HexToAddress(toStr)
		msg.to = &addr
	}

	if msg.gas.Cmp(big.NewInt(0)) == 0 {
		msg.gas = big.NewInt(50000000)
	}

	if msg.gasPrice.Cmp(big.NewInt(0)) == 0 {
		msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
	}

	header := be.bc.CurrentBlock().Header()
	vmenv := core.NewEnv(statedb, be.bc, msg, header)
	gp := new(core.GasPool).AddGas(common.MaxBig)
	res, gas, err := core.ApplyMessage(vmenv, msg, gp)

	return common.ToHex(res), gas.String(), err
}
コード例 #2
0
ファイル: flags.go プロジェクト: efaysal/etherapis
// MakeAddress converts an account specified directly as a hex encoded string or
// a key index in the key store to an internal account representation.
func MakeAddress(accman *accounts.Manager, account string) (a common.Address, err error) {
	// If the specified account is a valid address, return it
	if common.IsHexAddress(account) {
		return common.HexToAddress(account), nil
	}
	// Otherwise try to interpret the account as a keystore index
	index, err := strconv.Atoi(account)
	if err != nil {
		return a, fmt.Errorf("invalid account address or index %q", account)
	}
	hex, err := accman.AddressByIndex(index)
	if err != nil {
		return a, fmt.Errorf("can't get account #%d (%v)", index, err)
	}
	return common.HexToAddress(hex), nil
}
コード例 #3
0
ファイル: api.go プロジェクト: efaysal/etherapis
// StorageAt returns the data stores in the state for the given address and location.
func (be *registryAPIBackend) StorageAt(addr string, storageAddr string) string {
	block := be.bc.CurrentBlock()
	state, err := state.New(block.Root(), be.chainDb)
	if err != nil {
		return ""
	}
	return state.GetState(common.HexToAddress(addr), common.HexToHash(storageAddr)).Hex()
}
コード例 #4
0
ファイル: vault.go プロジェクト: efaysal/etherapis
// Store inserts a new authorized payment into the account vault for later
// redemption.
func (v *accountVault) Store(auth *authorization) {
	v.lock.Lock()
	defer v.lock.Unlock()

	consumer := common.HexToAddress(auth.Consumer)
	v.auths[consumer] = auth
	v.pends[consumer] = auth
}
コード例 #5
0
ファイル: backend.go プロジェクト: efaysal/etherapis
func (s *Ethereum) Etherbase() (eb common.Address, err error) {
	eb = s.etherbase
	if (eb == common.Address{}) {
		addr, e := s.AccountManager().AddressByIndex(0)
		if e != nil {
			err = fmt.Errorf("etherbase address must be explicitly specified")
		}
		eb = common.HexToAddress(addr)
	}
	return
}
コード例 #6
0
ファイル: vault.go プロジェクト: efaysal/etherapis
// Charge will redeem all pending payments made to this provider since startup.
func (v *accountVault) Charge(charger Charger) {
	v.lock.RLock()
	for _, auth := range v.pends {
		tx, err := charger.Charge(common.HexToAddress(auth.Consumer), common.HexToAddress(auth.Provider), auth.Nonce, new(big.Int).SetUint64(auth.Amount), common.FromHex(auth.Signature))
		if err != nil {
			log15.Error("Failed to charge payment", "authorization", auth, "error", err)
		} else {
			log15.Info("Payment charged", "tx", "http://testnet.etherscan.io/tx/"+tx.Hex())
		}
	}
	v.lock.RUnlock()

	v.lock.Lock()
	for consumer, auth := range v.auths {
		if v.pends[consumer] == auth {
			delete(v.pends, consumer)
		}
	}
	v.lock.Unlock()
}
コード例 #7
0
ファイル: vault.go プロジェクト: efaysal/etherapis
// Store inserts a new authorized payment into the vault for later redemption.
func (v *Vault) Store(auth *authorization) {
	v.lock.Lock()
	defer v.lock.Unlock()

	provider := common.HexToAddress(auth.Provider)
	if _, ok := v.vaults[provider]; !ok {
		v.vaults[provider] = &accountVault{
			auths: make(map[common.Address]*authorization),
			pends: make(map[common.Address]*authorization),
		}
	}
	v.vaults[provider].Store(auth)
}
コード例 #8
0
ファイル: registrar.go プロジェクト: efaysal/etherapis
// NameToAddr(from, name) queries the registrar for the address on name
func (self *Registrar) NameToAddr(from common.Address, name string) (address common.Address, err error) {
	if zero.MatchString(GlobalRegistrarAddr) {
		return address, fmt.Errorf("GlobalRegistrar address is not set")
	}

	nameHex, extra := encodeName(name, 2)
	abi := resolveAbi + nameHex + extra
	glog.V(logger.Detail).Infof("NameToAddr data: %s", abi)
	res, _, err := self.backend.Call(
		from.Hex(),
		GlobalRegistrarAddr,
		"", "", "",
		abi,
	)
	if err != nil {
		return
	}
	address = common.HexToAddress(res)
	return
}
コード例 #9
0
ファイル: block.go プロジェクト: efaysal/etherapis
func (h *Header) UnmarshalJSON(data []byte) error {
	var ext struct {
		ParentHash string
		Coinbase   string
		Difficulty string
		GasLimit   string
		Time       *big.Int
		Extra      string
	}
	dec := json.NewDecoder(bytes.NewReader(data))
	if err := dec.Decode(&ext); err != nil {
		return err
	}

	h.ParentHash = common.HexToHash(ext.ParentHash)
	h.Coinbase = common.HexToAddress(ext.Coinbase)
	h.Difficulty = common.String2Big(ext.Difficulty)
	h.Time = ext.Time
	h.Extra = []byte(ext.Extra)
	return nil
}
コード例 #10
0
ファイル: proxy.go プロジェクト: efaysal/etherapis
// ServeHTTP implements http.Handler, extracting and validating payment headers
// contained within the HTTP request. If payment information is accepted, the
// request is passed on to the internal service for execution. Otherwise the proxy
// short circuits the request and sends back an appropriate error.
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	reqLogger := p.logger.New("request-id", atomic.AddUint32(&p.autoid, 1))
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Expose-Headers", VerificationHeader)

	// Short circuit CORS pre-flight requests
	if r.Method == "OPTIONS" {
		reqLogger.Debug("Allowing CORS pre-flight request")
		w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
		return
	}
	// Allow head requests through for data APIs to query the content size
	if r.Method == "HEAD" {
		reqLogger.Debug("Allowing data HEAD request")
		w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Range")

		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()

		p.forward(w, res)
		return
	}
	// Retrieve the authorization header from the original request
	authHeader := r.Header.Get(AuthorizationHeader)
	reqLogger.Debug("Received an API request", "authorization", authHeader)

	// Ensure that all payment information are present
	if authHeader == "" {
		p.fail(w, &verification{Error: "Missing HTTP header: " + AuthorizationHeader})
		return
	}
	auth := new(authorization)
	if err := json.Unmarshal([]byte(authHeader), auth); err != nil {
		p.fail(w, &verification{Error: "Invalid authorization header: " + err.Error()})
		return
	}
	// Process the request and payment based on the proxy type
	switch p.kind {
	case CallProxy:
		// Make sure the consumer authorized the payment for this call
		consumer, provider := common.HexToAddress(auth.Consumer), common.HexToAddress(auth.Provider)

		if !p.verifier.Exists(consumer, provider) {
			p.fail(w, &verification{Unknown: true, Error: "Non existent API subscription"})
			return
		}

		nonce := p.verifier.Nonce(consumer, provider).Uint64()
		if auth.Nonce != nonce {
			p.fail(w, &verification{Error: "Invalid nonce", Nonce: nonce})
			return
		}

		valid, funded := p.verifier.Verify(consumer, provider, auth.Nonce, new(big.Int).SetUint64(auth.Amount), common.FromHex(auth.Signature))
		if !valid {
			p.fail(w, &verification{Error: "Invalid authorization signature"})
			return
		}
		if !funded {
			p.fail(w, &verification{Error: "Not enough funds available"})
			return
		}

		price := p.verifier.Price(consumer, provider).Uint64()
		if prev := p.vault.Fetch(provider, consumer); prev != nil && prev.Amount+price > auth.Amount {
			p.fail(w, &verification{
				Error:      "Not enough funds authorized",
				Authorized: prev.Amount,
				Proof:      prev.Signature,
				Need:       prev.Amount + price,
			})
			return
		}
		p.vault.Store(auth)

		// Execute the API internally and proxy the response
		reqLogger.Debug("Payment accepted for API invocation")
		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()
		p.forward(w, res)

	case DataProxy:
		// Since we're paying by the data, retrieve the amount first
		res, err := p.service(r)
		if err != nil {
			reqLogger.Error("Failed to process API request", "error", err)
			http.Error(w, "Failed to execute request", http.StatusInternalServerError)
			return
		}
		defer res.Body.Close()

		// Make sure the user authorized payment for all the requested data
		data := res.ContentLength
		if data > 0 /* TODO */ {
			reqLogger.Debug("Payment accepted for API stream", "data", data)
			p.forward(w, res)
		}
	}
}
コード例 #11
0
ファイル: main.go プロジェクト: efaysal/etherapis
func main() {
	// Parse and handle the command line flags
	flag.Parse()

	log15.Root().SetHandler(log15.LvlFilterHandler(log15.Lvl(*loglevelFlag), log15.StderrHandler))

	datadir := *datadirFlag
	if datadir == "" {
		datadir = filepath.Join(os.Getenv("HOME"), ".etherapis")
	}
	if err := os.MkdirAll(datadir, 0700); err != nil {
		log15.Crit("Failed to create data directory: %v", err)
		return
	}
	// Assemble and start the Ethereum client
	log15.Info("Booting Ethereum client...")
	client, err := geth.New(datadir, geth.TestNet)
	if err != nil {
		log15.Crit("Failed to create Ethereum client", "error", err)
		return
	}
	if err := client.Start(); err != nil {
		log15.Crit("Failed to start Ethereum client", "error", err)
		return
	}
	api, err := client.Attach()
	if err != nil {
		log15.Crit("Failed to attach to node", "error", err)
		return
	}
	// Wait for network connectivity and monitor synchronization
	log15.Info("Searching for network peers...")
	server := client.Stack().Server()
	for len(server.Peers()) == 0 {
		time.Sleep(100 * time.Millisecond)
	}
	go monitorSync(api)

	// Make sure we're at least semi recent on the chain before continuing
	waitSync(*syncFlag, api)

	var eth *eth.Ethereum
	err = client.Stack().Service(&eth)
	if err != nil {
		log15.Crit("Failed to fetch eth service", "error", err)
		return
	}
	contract, err := channels.Fetch(eth.ChainDb(), eth.EventMux(), eth.BlockChain())
	if err != nil {
		log15.Crit("Failed to get contract", "error", err)
		return
	}
	// Depending on the flags, execute different things
	switch {
	case *signFlag != "":
		var message struct {
			Provider string
			Nonce    uint64
			Amount   uint64
		}
		if err := json.Unmarshal([]byte(*signFlag), &message); err != nil {
			log15.Crit("Failed to decode data", "error", err)
			return
		}
		fmt.Println(message)
		accounts, err := eth.AccountManager().Accounts()
		if err != nil {
			log15.Crit("Failed retrieving accounts", "err", err)
		}
		if len(accounts) == 0 {
			log15.Crit("Signing data requires at least one account", "len", len(accounts))
			return
		}
		account := accounts[0]

		from := account.Address
		to := common.HexToAddress(message.Provider)

		hash := contract.Call("getHash", from, to, message.Nonce, message.Amount).([]byte)
		log15.Info("getting hash", "hash", common.ToHex(hash))

		eth.AccountManager().Unlock(from, "")
		sig, err := eth.AccountManager().Sign(account, hash)
		if err != nil {
			log15.Crit("signing vailed", "err", err)
			return
		}
		log15.Info("generated signature", "sig", common.ToHex(sig))

		return

	case *importFlag != "":
		// Account import, parse the provided .json file and ensure it's proper
		manager := eth.AccountManager()
		account, err := manager.Import(*importFlag, "")
		if err != nil {
			log15.Crit("Failed to import specified account", "path", *importFlag, "error", err)
			return
		}
		state, _ := eth.BlockChain().State()
		log15.Info("Account successfully imported", "account", fmt.Sprintf("0x%x", account.Address), "balance", state.GetBalance(account.Address))
		return

	case *accountsFlag:
		// Account listing requested, print all accounts and balances
		accounts, err := eth.AccountManager().Accounts()
		if err != nil || len(accounts) == 0 {
			log15.Crit("Failed to retrieve account", "accounts", len(accounts), "error", err)
			return
		}
		state, _ := eth.BlockChain().State()
		for i, account := range accounts {
			balance := float64(new(big.Int).Div(state.GetBalance(account.Address), common.Finney).Int64()) / 1000
			fmt.Printf("Account #%d: %f ether (http://testnet.etherscan.io/address/0x%x)\n", i, balance, account.Address)
		}
		return

	case *accGenFlag > 0:
		// We're generating and dumping demo accounts
		var nonce uint64
		var bank accounts.Account

		if *accLiveFlag {
			// If we want to fund generated accounts, make sure we can
			accounts, err := eth.AccountManager().Accounts()
			if err != nil || len(accounts) == 0 {
				log15.Crit("Failed to retrieve funding account", "accounts", len(accounts), "error", err)
				return
			}
			bank = accounts[0]
			if err := eth.AccountManager().Unlock(bank.Address, "gophergala"); err != nil {
				log15.Crit("Failed to unlock funding account", "account", fmt.Sprintf("0x%x", bank.Address), "error", err)
				return
			}
			state, _ := eth.BlockChain().State()
			nonce = state.GetNonce(bank.Address)

			log15.Info("Funding demo accounts with", "bank", fmt.Sprintf("0x%x", bank.Address), "nonce", nonce)
		}
		// Start generating the actual accounts
		log15.Info("Generating demo accounts", "count", *accGenFlag)
		for i := 0; i < *accGenFlag; i++ {
			// Generate a new account
			account, err := eth.AccountManager().NewAccount("pass")
			if err != nil {
				log15.Crit("Failed to generate new account", "error", err)
				return
			}
			// Export it's private key
			keyPath := fmt.Sprintf("0x%x.key", account.Address)
			if err := eth.AccountManager().Export(keyPath, account.Address, "pass"); err != nil {
				log15.Crit("Failed to export account", "account", fmt.Sprintf("0x%x", account.Address), "error", err)
				return
			}
			// Clean up so it doesn't clutter out accounts
			if err := eth.AccountManager().DeleteAccount(account.Address, "pass"); err != nil {
				log15.Crit("Failed to delete account", "account", fmt.Sprintf("0x%x", account.Address), "error", err)
				return
			}
			// If we're just testing, stop here
			if !*accLiveFlag {
				log15.Info("Account generated and exported", "path", keyPath)
				continue
			}
			// Oh boy, live accounts, send some ether to it and upload to the faucet
			allowance := new(big.Int).Mul(big.NewInt(10), common.Ether)
			price := new(big.Int).Mul(big.NewInt(50), common.Shannon)

			tx := types.NewTransaction(nonce, account.Address, allowance, big.NewInt(21000), price, nil)
			sig, err := eth.AccountManager().Sign(bank, tx.SigHash().Bytes())
			if err != nil {
				log15.Crit("Failed to sign funding transaction", "error", err)
				return
			}
			stx, err := tx.WithSignature(sig)
			if err != nil {
				log15.Crit("Failed to assemble funding transaction", "error", err)
				return
			}
			if err := eth.TxPool().Add(stx); err != nil {
				log15.Crit("Failed to execute transfer", "error", err)
				return
			}
			nonce++
			log15.Info("Account successfully funded", "account", fmt.Sprintf("0x%x", account.Address))

			// Upload the account to the faucet server
			key, err := ioutil.ReadFile(keyPath)
			if err != nil {
				log15.Crit("Failed to load private key", "error", err)
				return
			}
			res, err := http.Get("https://etherapis.appspot.com/faucet/fund?key=" + string(key))
			if err != nil {
				log15.Crit("Failed to upload private key to faucet", "error", err)
				return
			}
			res.Body.Close()

			log15.Info("Account uploaded to faucet", "account", fmt.Sprintf("0x%x", account.Address))
			os.Remove(keyPath)
		}
		// Just wait a bit to ensure transactions get propagated into the network
		log15.Info("Sleeping to ensure transaction propagation")
		time.Sleep(10 * time.Second)
		return

	case len(*queryFlag) > 0:
		// Check whether any of our accounts are subscribed to this particular service
		accounts, err := eth.AccountManager().Accounts()
		if err != nil || len(accounts) == 0 {
			log15.Crit("Failed to retrieve account", "accounts", len(accounts), "error", err)
			return
		}
		provider := common.HexToAddress(*queryFlag)
		log15.Info("Checking subscription status", "service", fmt.Sprintf("0x%x", provider))
		for i, account := range accounts {
			// Check if a subscription exists
			if !contract.Exists(account.Address, provider) {
				fmt.Printf("Account #%d: [0x%x]: not subscribed.\n", i, account.Address)
				continue
			}
			// Retrieve the current balance on the subscription
			ethers := contract.Call("getChannelValue", contract.ChannelId(account.Address, provider)).(*big.Int)
			funds := float64(new(big.Int).Div(ethers, common.Finney).Int64()) / 1000

			fmt.Printf("Account #%d: [0x%x]: subscribed, with %v ether(s) left.\n", i, account.Address, funds)
		}
		return

	case len(*subToFlag) > 0:
		// Subscription requested, make sure all the details are provided
		accounts, err := eth.AccountManager().Accounts()
		if err != nil || len(accounts) < *subAccFlag {
			log15.Crit("Failed to retrieve account", "accounts", len(accounts), "requested", *subAccFlag, "error", err)
			return
		}
		account := accounts[*subAccFlag]

		// Check if a subscription exists
		provider := common.HexToAddress(*subToFlag)
		if contract.Exists(account.Address, provider) {
			log15.Error("Account already subscribed", "index", *subAccFlag, "account", fmt.Sprintf("0x%x", account.Address), "service", fmt.Sprintf("0x%x", provider))
			return
		}
		// Try to subscribe and wait until it completes
		keystore := client.Keystore()
		key, err := keystore.GetKey(account.Address, "")
		if err != nil {
			log15.Crit("Failed to unlock account", "account", fmt.Sprintf("0x%x", account.Address), "error", err)
			return
		}
		amount := new(big.Int).Mul(big.NewInt(int64(1000000000**subFundFlag)), common.Shannon)

		log15.Info("Subscribing to new payment channel", "account", fmt.Sprintf("0x%x", account.Address), "service", fmt.Sprintf("0x%x", provider), "ethers", *subFundFlag)
		pend := make(chan *channels.Channel)
		tx, err := contract.NewChannel(key.PrivateKey, provider, amount, big.NewInt(1), func(sub *channels.Channel) { pend <- sub })
		if err != nil {
			log15.Crit("Failed to create subscription", "error", err)
			return
		}
		if err := eth.TxPool().Add(tx); err != nil {
			log15.Crit("Failed to execute subscription", "error", err)
			return
		}
		log15.Info("Waiting for subscription to be finalized...", "tx", tx)
		log15.Info("Successfully subscribed", "channel", fmt.Sprintf("%x", (<-pend).Id))
		return
	}

	if *testFlag {
		accounts, err := eth.AccountManager().Accounts()
		if err != nil {
			log15.Crit("Failed retrieving accounts", "err", err)
		}
		if len(accounts) < 2 {
			log15.Crit("Test vectors requires at least 2 accounts", "len", len(accounts))
			return
		}

		log15.Info("Attempting channel test vectors...")
		from := accounts[0].Address
		eth.AccountManager().Unlock(from, "")

		to := accounts[0].Address
		log15.Info("making channel name...", "from", from.Hex(), "to", to.Hex(), "ID", contract.ChannelId(from, to).Hex())
		log15.Info("checking existence...", "exists", contract.Exists(from, to))

		amount := big.NewInt(1)
		hash := contract.Call("getHash", from, to, 0, amount).([]byte)
		log15.Info("signing data", "to", to.Hex(), "amount", amount, "hash", common.ToHex(hash))

		sig, err := eth.AccountManager().Sign(accounts[0], hash)
		if err != nil {
			log15.Crit("signing vailed", "err", err)
			return
		}
		log15.Info("verifying signature", "sig", common.ToHex(sig))

		if contract.ValidateSig(from, to, 0, amount, sig) {
			log15.Info("signature was valid and was verified by the EVM")
		} else {
			log15.Crit("signature was invalid")
			return
		}

		log15.Info("verifying payment", "sig", common.ToHex(sig))
		if valid, _ := contract.Verify(from, to, 0, amount, sig); valid {
			log15.Info("payment was valid and was verified by the EVM")
		} else {
			log15.Crit("payment was invalid")
			return
		}

		log15.Info("verifying invalid payment", "nonce", 1)
		if valid, _ := contract.Verify(from, to, 1, amount, sig); valid {
			log15.Crit("payment was valid")
			return
		} else {
			log15.Info("payment was invalid")
		}
	}

	// If we're running a proxy, start processing external requests
	if *proxyFlag != "" {
		// Subscription requested, make sure all the details are provided
		accounts, err := eth.AccountManager().Accounts()
		if err != nil || len(accounts) < *subAccFlag {
			log15.Crit("Failed to retrieve account", "accounts", len(accounts), "requested", *subAccFlag, "error", err)
			return
		}
		account := accounts[*subAccFlag]
		if err := eth.AccountManager().Unlock(account.Address, ""); err != nil {
			log15.Crit("Failed to unlock provider account", "account", fmt.Sprintf("0x%x", account.Address), "error", err)
			return
		}
		log15.Info("Setuping vault...", "owner", account.Address.Hex())

		// Create the payment vault to hold the various authorizations
		vault := proxy.NewVault(NewCharger(account, eth.TxPool(), contract, eth.AccountManager()))
		vault.AutoCharge(*chargeFlag)

		for i, config := range strings.Split(*proxyFlag, ",") {
			// Split the proxy configuration
			parts := strings.Split(config, ":")
			if len(parts) != 3 {
				log15.Crit("Invalid proxy config", "config", config)
				return
			}
			extPort, err := strconv.Atoi(parts[0])
			if err != nil || extPort < 0 || extPort > 65535 {
				log15.Crit("Invalid external port number", "port", parts[0])
				return
			}
			intPort, err := strconv.Atoi(parts[1])
			if err != nil || intPort < 0 || intPort > 65535 {
				log15.Crit("Invalid internal port number", "port", parts[1])
				return
			}
			var kind proxy.ProxyType
			switch strings.ToLower(parts[2]) {
			case "call":
				kind = proxy.CallProxy
			case "data":
				kind = proxy.DataProxy
			default:
				log15.Crit("Unsupported proxy type", "type", parts[2], "allowed", []string{"call", "data"})
				return
			}
			// Create and start the new proxy
			gateway := proxy.New(i, extPort, intPort, kind, contract, vault)
			go func() {
				if err := gateway.Start(); err != nil {
					log15.Crit("Failed to start proxy", "error", err)
					os.Exit(-1)
				}
			}()
		}
		// Wait indefinitely, for now at least
		for {
			time.Sleep(time.Second)
		}
	}
	// Clean up for now
	log15.Info("Terminating Ethereum client...")
	if err := client.Stop(); err != nil {
		log15.Crit("Failed to terminate Ethereum client", "error", err)
		return
	}
}
コード例 #12
0
ファイル: genesis.go プロジェクト: efaysal/etherapis
// WriteGenesisBlock writes the genesis block to the database as block number 0
func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) {
	contents, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}

	var genesis struct {
		Nonce      string
		Timestamp  string
		ParentHash string
		ExtraData  string
		GasLimit   string
		Difficulty string
		Mixhash    string
		Coinbase   string
		Alloc      map[string]struct {
			Code    string
			Storage map[string]string
			Balance string
		}
	}

	if err := json.Unmarshal(contents, &genesis); err != nil {
		return nil, err
	}

	// creating with empty hash always works
	statedb, _ := state.New(common.Hash{}, chainDb)
	for addr, account := range genesis.Alloc {
		address := common.HexToAddress(addr)
		statedb.AddBalance(address, common.String2Big(account.Balance))
		statedb.SetCode(address, common.Hex2Bytes(account.Code))
		for key, value := range account.Storage {
			statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
		}
	}
	root, stateBatch := statedb.CommitBatch()

	difficulty := common.String2Big(genesis.Difficulty)
	block := types.NewBlock(&types.Header{
		Nonce:      types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
		Time:       common.String2Big(genesis.Timestamp),
		ParentHash: common.HexToHash(genesis.ParentHash),
		Extra:      common.FromHex(genesis.ExtraData),
		GasLimit:   common.String2Big(genesis.GasLimit),
		Difficulty: difficulty,
		MixDigest:  common.HexToHash(genesis.Mixhash),
		Coinbase:   common.HexToAddress(genesis.Coinbase),
		Root:       root,
	}, nil, nil, nil)

	if block := GetBlock(chainDb, block.Hash()); block != nil {
		glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number")
		err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
		if err != nil {
			return nil, err
		}
		return block, nil
	}

	if err := stateBatch.Write(); err != nil {
		return nil, fmt.Errorf("cannot write state: %v", err)
	}
	if err := WriteTd(chainDb, block.Hash(), difficulty); err != nil {
		return nil, err
	}
	if err := WriteBlock(chainDb, block); err != nil {
		return nil, err
	}
	if err := WriteBlockReceipts(chainDb, block.Hash(), nil); err != nil {
		return nil, err
	}
	if err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()); err != nil {
		return nil, err
	}
	if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
		return nil, err
	}
	return block, nil
}
コード例 #13
0
ファイル: api.go プロジェクト: efaysal/etherapis
// Transact forms a transaction from the given arguments and submits it to the
// transactio pool for execution.
func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
	if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(toStr) {
		return "", errors.New("invalid address")
	}

	var (
		from             = common.HexToAddress(fromStr)
		to               = common.HexToAddress(toStr)
		value            = common.Big(valueStr)
		gas              *big.Int
		price            *big.Int
		data             []byte
		contractCreation bool
	)

	if len(gasStr) == 0 {
		gas = big.NewInt(90000)
	} else {
		gas = common.Big(gasStr)
	}

	if len(gasPriceStr) == 0 {
		price = big.NewInt(10000000000000)
	} else {
		price = common.Big(gasPriceStr)
	}

	data = common.FromHex(codeStr)
	if len(toStr) == 0 {
		contractCreation = true
	}

	nonce := be.txPool.State().GetNonce(from)
	if len(nonceStr) != 0 {
		nonce = common.Big(nonceStr).Uint64()
	}

	var tx *types.Transaction
	if contractCreation {
		tx = types.NewContractCreation(nonce, value, gas, price, data)
	} else {
		tx = types.NewTransaction(nonce, to, value, gas, price, data)
	}

	acc := accounts.Account{from}
	signature, err := be.am.Sign(acc, tx.SigHash().Bytes())
	if err != nil {
		return "", err
	}
	signedTx, err := tx.WithSignature(signature)
	if err != nil {
		return "", err
	}

	be.txPool.SetLocal(signedTx)
	if err := be.txPool.Add(signedTx); err != nil {
		return "", nil
	}

	if contractCreation {
		addr := crypto.CreateAddress(from, nonce)
		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
	} else {
		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
	}

	return signedTx.Hash().Hex(), nil
}
コード例 #14
0
ファイル: contract.go プロジェクト: efaysal/etherapis
	"strings"
	"sync"

	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/common"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/core"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/core/types"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/core/vm"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/crypto"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/eth/filters"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/ethdb"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/event"
)

// contractAddress is the static address on which the contract resides
var contractAddress = common.HexToAddress("0x8e517c8f4cc7714ef4723d0b70205c53d264c142")

// signFn is a signer function callback when the contract requires a method to
// sign the transaction before submission.
type signFn func(*types.Transaction) (*types.Transaction, error)

// Channels is the channels contract reflecting that on the ethereum network. The
// channels contract handles all validation and verifications of payments and
// allows you to redeem cheques.
//
// Channels implements the proxy.Verifier and proxy.Charges interfaces.
type Channels struct {
	abi        abi.ABI
	blockchain *core.BlockChain

	filters *filters.FilterSystem
コード例 #15
0
ファイル: canary.go プロジェクト: efaysal/etherapis
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
	"math/big"

	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/common"
	"github.com/gophergala2016/etherapis/etherapis/Godeps/_workspace/src/github.com/ethereum/go-ethereum/core/state"
)

var (
	jeff      = common.HexToAddress("959c33de5961820567930eccce51ea715c496f85")
	vitalik   = common.HexToAddress("c8158da0b567a8cc898991c2c2a073af67dc03a9")
	christoph = common.HexToAddress("7a19a893f91d5b6e2cdf941b6acbba2cbcf431ee")
	gav       = common.HexToAddress("539dd9aaf45c3feb03f9c004f4098bd3268fef6b")
)

// Canary will check the 0'd address of the 4 contracts above.
// If two or more are set to anything other than a 0 the canary
// dies a horrible death.
func Canary(statedb *state.StateDB) bool {
	var r int
	if (statedb.GetState(jeff, common.Hash{}).Big().Cmp(big.NewInt(0)) > 0) {
		r++
	}
	if (statedb.GetState(gav, common.Hash{}).Big().Cmp(big.NewInt(0)) > 0) {
		r++